Skip to content

Commit

Permalink
handle the race condition in updating operationName
Browse files Browse the repository at this point in the history
If a new query string is passed in (and `componentWillReceiveProps` is called) without manually editing query (e.g. programmatically modifying the content within the editor without key events), it's possible to have both `_updateQueryFacts` and `componentWillReceiveProps` tryint to update `operationName` by calling the `setState` method, most often times the one in `componentWillReceiveProps` winning incorrectly. The fix is to treat the outcome from `_updateQueryFacts` as truth and properly updating what to update during the component lifecycle.
  • Loading branch information
asiandrummer committed Feb 24, 2017
1 parent d040911 commit a452374
Showing 1 changed file with 25 additions and 12 deletions.
37 changes: 25 additions & 12 deletions src/components/GraphiQL.js
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,17 @@ export class GraphiQL extends React.Component {
if (nextSchema !== this.state.schema ||
nextQuery !== this.state.query ||
nextOperationName !== this.state.operationName) {
this._updateQueryFacts(nextQuery);
const updatedQueryAttributes = this._updateQueryFacts(
nextQuery,
nextOperationName,
nextSchema,
);

if (updatedQueryAttributes !== undefined) {
nextOperationName = updatedQueryAttributes.operationName;

this.setState({ ...updatedQueryAttributes.queryFacts });
}
}

// If schema is not supplied via props and the fetcher changed, then
Expand Down Expand Up @@ -650,34 +660,37 @@ export class GraphiQL extends React.Component {

handleEditQuery = debounce(100, value => {
if (this.state.schema) {
this._updateQueryFacts(value);
this.setState(
this._updateQueryFacts(
value,
this.state.operationName,
this.state.schema,
),
);
}
this.setState({ query: value });
if (this.props.onEditQuery) {
return this.props.onEditQuery(value);
}
})

_updateQueryFacts = query => {
const queryFacts = getQueryFacts(this.state.schema, query);
_updateQueryFacts = (query, operationName, schema) => {
const queryFacts = getQueryFacts(schema, query);
if (queryFacts) {
// Update operation name should any query names change.
const operationName = getSelectedOperationName(
const updatedOperationName= getSelectedOperationName(
this.state.operations,
this.state.operationName,
operationName,
queryFacts.operations
);

// Report changing of operationName if it changed.
const onEditOperationName = this.props.onEditOperationName;
if (onEditOperationName && operationName !== this.state.operationName) {
onEditOperationName(operationName);
if (onEditOperationName && operationName !== updatedOperationName) {
onEditOperationName(updatedOperationName);
}

this.setState({
operationName,
...queryFacts
});
return { operationName: updatedOperationName, ...queryFacts };
}
}

Expand Down

0 comments on commit a452374

Please sign in to comment.