Jesper We Jesper We - 9 days ago 14
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

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