Jesper We Jesper We - 10 months ago 83
React JSX Question

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

In my Redux store I am storing an accountId. This is stored by the

<Login>
component after a successful authorization. The
<Login>
component only receives the
accountId
(inside a JWT), not the full Account object with all its properties.

The
accountId
can also be modified from by other actions from other components.

When the
accountId
gets modified for whatever reason I want to fire a new GraphQL query for the full Account document, and store that in Redux too.

To this end I have created a component. I initially put the Redux dispatch pieces in
componentWillUpdate()
, but then it does not work (it does not receive the completed GraphQL query results). If I put it in
render()
like below, it works:

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 );


The above component works as intended. But it throws a warning when I call the dispatch:

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


So apparently I m not doing things the right way. How can I structure this so that I get the results and am able to store them back into Redux without warning?

Answer Source

You could try putting the logic in componentDidUpdate if the only issue is the warning.