0
votes

I am using React and Redux in a project I’ve two components a parent and a child.

The parent component passes some props to the child when the child component receives those props it calls some action which change some of the props (async) that the parent passed to its child. Now my redux-store shows that the data has successfully stored in it. But my child component doesn’t re-render itself.

Parent Component:

class Parent extends React.Component {
      getChilds(){
       let child = [];
       let i = 0;
       for (let keys in this.props.home.data) {
         child[i] = (
         <Child title={keys} data={this.props.home.data[keys]} key={keys} />
        );
         i++;
         if (i === 6) break;
       }

      return Rows;
      }
    render(){
     return (
       <div>
        <h1>I am gonna call my child </h1>
        {this.getChilds()}
       </div>)
      }
}

Child Component:

    class Child extends React.Component {
     // Here I'm not sure which lifecycle method to use to i'm gonna use
    // componentDidMount
    componentDidMount(){
      if(this.props.data.items.length === 0){
        // calling an action to fill this.props.data.items array with data
       this.props.getData(this.props.data.id);
      }
     }
     getGrandSong(){
     let grandSons = [];
     if(this.props.data.items.length > 0){
       grandSons = this.props.data.items.map( item => <GrandSon item={item} 
                     />);
      }
     return grandSons;
     }
    render(){
      return (
       <div>
        <h1> I am the child component and I will call my own child </h1>
        {this.getGrandSon()}
       </div>
     )
   }

Props are updated when I check the props in react-dev tool.

1
This seems weird. First you call this.props.getData in the Child, but you don't pass such prop getData in the Parent when you call <Child .. />. Second, I don't see any redux on the scene. Third, there are typos like defining getGrandSong then calling getGrandSon(). I think this piece of code wouldn't work for many such reasons. - amik
He could be mapping getData with Redux and didn't include it, which would be odd, but of course those typos do need to be corrected if that's the original code. Please post the getData function and any relevant reducers so we can see where the async call is taking place. - Chris B.
this.props.getData is a redux action. I am using connect to get. getGrandSong is a syntax mistake it should be getGrandSon. - Zullu
in react-dev-tool props are changing. - Zullu
I think we are missing a few things 1. We don't know what state looks like after getData is dispatched, 2. We don't know what component is subscribing to state changing (where are you calling mapStateToProps/mapDispatchToProps) - Dan D

1 Answers

0
votes

You need the data to re-render whenever the prop changes, so you can call it on the render function and implement shouldComponentUpdate() to deeply compare props and call render().

So, in this case:

class Child extends React.Component {
    componentDidMount(){
      if(this.props.data.items.length === 0){
        // calling an action to fill this.props.data.items array with data
       this.props.getData(this.props.data.id);
      }
     }
    shouldComponentUpdate(nextProps){
        if(this.props.data.items.length === nextProps.data.items.length){
            for(let i=0; i< nextProps.data.items ; i ++){
                if(nextProps.data.items[i] !== this.props.data.items[i]) return true;
            }
        }
        return true;
    }
    render(){
        const getGrandSong = () => {
            let grandSons = [];
            if(this.props.data.items.length > 0){
                grandSons = this.props.data.items.map( item => <GrandSon item={item} />);
            }
            return grandSons;
        }
      return (
       <div>
        <h1> I am the child component and I will call my own child </h1>
        {getGrandSon()}
       </div>
     )
   }