how and when to call a react component methods after state change from redux

14,205

Solution 1

More detailed examples would be useful, but based on what you have here, I think I see what you're getting at.

Short answer: Yes, this is a symptom of not moving enough logic to the action creators. Ideally, your component should be a pure view component. No need for componentWillReceiveProps in most cases - you simply render whatever the props are and that's that. This is why Abramov (creator of redux) argues for functional components. More on that here.

If you need to perform other actions after an async call returns with some data, you would do that, as you said, in the action creator. I'm going to go with an example that uses thunks:

EDIT: I added an example of the component passing a reference to the audio player as an argument to the action. That way, the action can manipulate after the async step.

//An async action creator that uses the thunk pattern.
//You could call this method from your component just like any other
//action creator.

export function getMaDatums(audioPlayer, audioContext) {
  return function (dispatch) {

    //make the actual call to get the data
    return fetch(`http://<your stuff here>`)
      .then(data => {

        //call dispatch again to do stuff with the data
        dispatch(gotDataAction(data));

        //call dispatch some more to take further actions
        dispatch(...);

        //since the component passed us references to these, we can
        //interact with them here, after our data has loaded! FTW!
        audioPlayer.doTheThings();
        audioSession.doTheOtherThings();

        //plus anything else you want...
      });
  }
}

If you want to learn more about the doing async stuff with redux, or for that matter, interfacing with stateful libraries from your redux app, I highly recommend giving the redux documentation a good read. The basis of the thunk example above came from here.

Good luck and have fun with React + Redux!

Solution 2

Coming back to my own question years later now.

If I can use a functional component, I would use the react hook useEffect. If the logic can be externalised then perhaps in a saga.

useEffect(() => {
  methodToCallIfPropChanges()
}, [watchedProp]);

Solution 3

An update can be caused by changes to props or state. These methods are called in the following order when a component is being re-rendered:

  • static getDerivedStateFromProps()
  • shouldComponentUpdate()
  • render()
  • getSnapshotBeforeUpdate()
  • componentDidUpdate() Try to use componentDidUpdate()

React docs https://reactjs.org/docs/react-component.html#updating

Share:
14,205
njorlsaga
Author by

njorlsaga

Updated on June 22, 2022

Comments

  • njorlsaga
    njorlsaga almost 2 years

    In a single react component a user clicks a button => which calls a method => triggers an action => async fetch => reducer updates state => component receives new props.

    back in the original component that triggered the action I have been using:

    componentWillReceiveProps(nextProps){
        if(nextProps.someProp !== this.props.someProp){
            //ok new prop is here
            this.someMethod(nextProps.someProp);
        }
    }
    

    Am I going about this in the right way?

    It just seems somewhat clunky and detached as a callback mechanism from the user action or change of state. It just makes following the logical flow of the component harder once there are a few of these, I have a component with 3 of these and already think it's not as easy to reason about especially when they are part of a related flow a > b > c . And I have ended up with this kind of thing:

    componentWillReceiveProps(nextProps){
    
        if(this.patchJavaScriptWillLoad(nextProps)){
            this.createPatchInstance();
            // method fires an action which will also result in state change that triggers the below.
        }
    
        if(this.patchInstanceWillBeReady(nextProps)){
            this.startPatchAudio(nextProps.webAudioPatch.instance);
            // method fires an action which will also result in state change that triggers the below.
        }
    
        if(this.patchParametersWillChange(nextProps)){
            this.updateWebAudioPatchParameters(nextProps.webAudioPatchParameters);
        }
    }
    
    // abstracted away if conditions to make componentWillReceiveProps more readable. 
    

    But is this how it should be done or is this a symptom of not moving enough logic to action creators?