如何构造一个从 redux 接收 prop 的组件,进行查询并将结果保存回 redux?

How to structure a component that receives a prop from redux, makes query and saves result back to redux?

在我的 Redux 商店中,我存储了一个 accountId。这是在成功授权后由 <Login> 组件存储的。 <Login> 组件仅接收 accountId (在 JWT 内),而不是具有所有属性的完整帐户对象。

accountId 也可以通过其他组件的其他操作进行修改。

accountId 由于某种原因被修改时,我想为完整的帐户文档触发一个新的 GraphQL 查询,并将其也存储在 Redux 中。

为此我创建了一个组件。我最初将 Redux dispatch 片段放在 componentWillUpdate() 中,但后来它不起作用(它没有收到完成的 GraphQL 查询结果)。如果我像下面这样把它放在 render() 中,它就会起作用:

import React from 'react';
import { graphql } from 'react-apollo';
import gql from 'graphql-tag';
import { message } from 'antd';

// This service receives an accountId prop from Redux, and returns the complete account record
// to Redux once the graphQL query completes.

class AccountService extends React.Component {

    render() {
        if( !this.props.accountId ) {
            this.props.onAccount( null ); // Logged out -> Redux
        } else {
            if( this.props.data && this.props.data.error ) {
                console.log( this.props.data.error.message );
                message.error( this.props.data.error.message, 20 );
            }

            if( this.props.data && this.props.data.loading === false ) {
                if( this.props.data.accountById ) {
                    let account = {
                        firstName: this.props.data.accountById.firstName,
                        lastName: this.props.data.accountById.lastName,
                        // ...etc.
                    };
                    this.props.onAccount( account ); // -> Redux dispatch
                }
            }
        }

        return ( null );
    }
}

const accountQuery = gql`
query ($accountId: Int!) {accountById(id:$accountId) {
  firstName,
  lastName,
  // ...etc.
}}`;

export default graphql( accountQuery, {
    options: ( { accountId } ) => ({ variables: { accountId: accountId || 0 } }),
} )( AccountService );

以上组件按预期工作。但是当我调用调度时它会发出警告:

Warning: setState(...): Cannot update during an existing state transition

所以显然我做事的方式不对。我如何构建它以便获得结果并能够在没有警告的情况下将它们存储回 Redux?

如果唯一的问题是警告,您可以尝试将逻辑放在 componentDidUpdate 中。

您应该使用 componentWillReceiveProps 在收到新的 accountId 时获取帐户信息。

试试这个:

class AccountService extends React.Component {

    componentDidMount() {
      // you may need this for initial rendering
      fetchAccountInfo(this.props);
    }

    componentWillReceiveProps(nextProps) {
        // do the GraphQL fetch only when account-ID is changed
        if (this.props.accountId !== nextProps.accountId) {
            fetchAccountInfo(nextProps); // fetch account info for new props
        }
    }

    fetchAccountInfo() {
        if( !this.props.accountId ) {
            this.props.onAccount( null ); // Logged out -> Redux
        } else {
            if( this.props.data && this.props.data.error ) {
                console.log( this.props.data.error.message );
                message.error( this.props.data.error.message, 20 );
            }

            if( this.props.data && this.props.data.loading === false ) {
                if( this.props.data.accountById ) {
                    let account = {
                      firstName: this.props.data.accountById.firstName,
                      lastName: this.props.data.accountById.lastName,
                      // ...etc.
                    };
                    this.props.onAccount(account); // -> Redux dispatch
                }
            }
        }
    }

    render() {
      // ...
    }
}

切勿在 render() 内 dipatch 动作或 setState(您很容易陷入重新渲染循环)。可能是这导致了警告:

Warning: setState(...): Cannot update during an existing state transition