React:Apollo Client:在现有状态转换期间无法更新

时间:2018-03-31 01:35:00

标签: reactjs graphql react-apollo

我正在尝试创建一个包装Apollo Client的Query组件的组件。我使用apollo-link-state进行本地状态管理,我希望有一个错误通知系统,通知用户所有的事情。

我的组件看起来像这样......

export class Viewer extends React.Component {
  static propTypes = {
    children: PropTypes.func
  };

  render() {
    const { children } = this.props;
    return (
      <Query query={GET_VIEWER}>
        {({ data, client, error }) => {
          if (error) {
            client.mutate({
              mutation: ADD_NOTIFICATION,
              variables: { message: unpackApolloErr(error), type: 'Error' }
            });
          }

          return children(data.viewer ? data.viewer : user);
        }}
      </Query>
    );
  }
}

但是当它试图用变异添加错误时,我得到了反应错误..

Warning: forceUpdate(...): Cannot update during an existing state transition (such as within `render` or another component's constructor). Render methods should be a pure function of props and state; constructor side-effects are an anti-pattern, but can be moved to `componentWillMount`.

我没有看到一个显而易见的方法,如果客户端作为渲染道具提供并且无法使用,我也不明白为什么会发生这种情况......我一定不能错过一些简单的东西但是我看不出它是什么

2 个答案:

答案 0 :(得分:0)

答案结果是,在使用onError https://www.apollographql.com/docs/link/links/error.html时,客户端在this函数apollo-link-error中可用

我之前尝试使用onError来访问客户端,但是即使客户端是在onError之后声明的,调用它的范围确实包含客户端也不是很明显处理

// client is available here even though it is defined first 
const err = onError({ graphQLErrors }) => {
    this.client.mutate({ mutation: ADD_ERROR, variables: { graphQLErrors }})
}

const client = new ApolloClient({
    cache,
    link: ApolloLink.from([err, httpLink])
})

答案 1 :(得分:0)

之所以存在Warning: forceUpdate,可能是因为Apollo内部会在发生突变时导致forceUpdate。因此,突变应该采用render方法。

在Apollo错误后处理突变的最佳方法是添加onError链接,如https://www.apollographql.com/docs/react/features/error-handling.html#network

中所述
// Add errorLink into Apollo Client
const errorLink = onError(({ graphQLErrors, networkError, operation }) => {
  this.client.mutate({ mutation: ..., variables: {}});
});


const client = new ApolloClient({
  cache,
  link: ApolloLink.from([err, httpLink])
})