在 Apollo 查询组件 returns 结果后调度 redux 操作

Dispatch redux action after Apollo Query component returns result

使用旧方法:

graphql(GET_PROJECTS_BY_USER_ID, {
    options: ownProps => ({
        skip: !ownProps.loggedUser.id,
    }),
    props: ({ data }) => {
        return data;
    },
});

我可以在 componentWillReceiveProps 生命周期内捕获项目列表并在那里调度 redux 操作:

componentWillReceiveProps(nextProps) {
    if (!nextProps.loading && this.props.loading) {
        this.props.setProjects(nextProps.getProjects);
    }
}

现在我正在试用 Apollo 的 <Query/> 组件,但我不知道如何正确地发送一个动作:

render() {
    return (
        <Query
            query={GET_PROJECTS_BY_USER_ID}
            skip={!this.props.loggedUserId}
        >
            {({ loading, data: { getProjects: projects } }) => {
                if (loading) return 'Loading ...';

                this.props.setProjects(projects); // no good

                // return projects
            }}
        </Query>
    );
}

这将导致以下警告:

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.

问题是使用 <Query>,componentWillMount` 将不再被调用。

新的 Query 组件使用 render props 模式。作为组件的子组件传入的函数在 Query 的 render 方法中被调用,这意味着您无权访问该组件的任何其他生命周期方法在函数里面。为了解决这个问题,您必须创建一个额外的组件来实现您需要的生命周期方法。只有一种方法可以做到这一点:

class DoSomethingOnce extends Component {
  componentWillMount () {
    this.props.action()
  }
  render () {
    return this.props.children || null
  }
}

<Query
  query={GET_PROJECTS_BY_USER_ID}
  skip={!this.props.loggedUserId}
>
  {({ loading, data: { getProjects: projects } }) => {
    if (loading) return 'Loading ...';
    <DoSomethingOnce action={() => setProjects(projects)}>
      // whatever else you're going to render
    </DoSomethingOnce>
  }}
</Query>

或者,带有 componentDidMount 的组件可以只进行所有渲染,而不是将责任推给它的子组件。您也可以随时使用 reactions/component.

这样的库

这实际上与您使用 graphql HOC 时没有什么不同——您仍然必须将该 HOC 包装在实现 componentDidMount.

的组件周围