13

I'm new to React. I'm stuck on this, would really appreciate some help!

A parent component will pass an array into this child component. When I console.log(this.props.repairs) it shows me an array of 4. I am trying to update this.state.sortedDataList whenever the array of repairs is passed in. The console.log(this.state) is still showing sortedDataList as an empty array.

What am I doing wrong? Thanks so much, appreciate any help.

class Repairs extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      sortedDataList: []
    };
  }

  componentWillReceiveProps(nextProps) {
    if(this.props != nextProps) {
      this.setState({
        sortedDataList: this.props.repairs
      });
    }
  }

  render() {
    console.log(this.props);
    console.log(this.state);

    return (
      <div></div>
    );
  }
}
Irene Li
  • 219
  • 1
  • 2
  • 7
  • 2
    Answers from Jayce444 and Shubham are correct. I would add that you should really determine if you need state to represent what you want to show on the page or if you can strictly use props. Having 'pure' functional react components (components that only render based on what is in props) is always a good goal. – Special Character Jan 11 '17 at 04:00
  • Why are you setting props to state? what good does that do for you? you now have a shadow of the same data stored in state as well as props. To add to that props are considered immutable meaning you don't and shouldn't change them. setting props to state like this is making your immutable data now mutable, which is an Anti-Pattern and is a big no no. Read this to understand more http://stackoverflow.com/a/28785276/2733506 – John Ruddell Jan 11 '17 at 05:13

3 Answers3

8

Never mind, found my silly mistake! If anyone else gets stuck on this in the future...

componentWillReceiveProps(nextProps) {
  if(this.props != nextProps) {
    this.setState({
      sortedDataList: nextProps.repairs
    });
  }
}
Irene Li
  • 219
  • 1
  • 2
  • 7
3

componentWillReceiveProps isn't called on the first render. That is the reason that you don't see any update in the state

From the React Docs:

"Invoked when a component is receiving new props. This method is not called for the initial render."

If you want to make the change only first time you can make use of componentWillMount lifecycle function and update the state. On subsequent changed you componentWillReceiveProps will be called.

class Repairs extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      sortedDataList: []
    };
  }

  componentWillMount() {
   
      this.setState({
        sortedDataList: this.props.repairs
      }, () => console.log(this.state.sortedDataList));
    
  }
   componentWillReceiveProps(nextProps) {
    if(this.props != nextProps) {
      this.setState({
        sortedDataList: nextProps.repairs
      });
    }
  }

  render() {
    console.log("r",this.props);
    console.log("r",this.state);

    return (
      <div></div>
    );
  }
}

class App extends React.Component {
  render() {
    var arr = ["1", "2", "3"];
    return (
      <div >
        <Repairs repairs={arr}/>
      </div>
    )
  }
}
ReactDOM.render(<App/>, document.getElementById('app'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.14.8/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.14.8/react-dom.min.js"></script>
<div id="app"></div>
Shubham Khatri
  • 270,417
  • 55
  • 406
  • 400
  • Thanks for answer. Actually, I noticed, when I first hit the route, all the console.logs go through as the initialState of empty array. But after the async calls sends the props to the parent and that gets passed down, and it does hit the componentWillReceiveProps function. But this got me questioning the lifecycle, and I found my silly mistake. It should be this.setState({ sortedDataList: nextProps.repairs }); – Irene Li Jan 11 '17 at 04:13
0

In your constructor

this.state = {
  sortedDataList: []
};

You initially set state to an empty array, so on first render it'll be empty. Then, whenever the props are changed, it'll get updated via componentWillReceiveProps().

As Shubham said, componentWillReceiveProps() isn't called on the first render. If you want the state to reflect the props right from the first render, you'd have to put it in the constructor like so:

this.state = {
  sortedDataList: this.props.repair
};
Jayce444
  • 8,725
  • 3
  • 27
  • 43
  • 2
    assigning props to initial state is an anti pattern and we shouldn't be following that. http://stackoverflow.com/questions/28785106/reactjs-why-is-passing-the-component-initial-state-a-prop-an-anti-pattern. Although I agree its a simple solution, but I purposfully didn't mention it for the above reason – Shubham Khatri Jan 11 '17 at 03:55