1

I'm trying to replace an initially empty array with an array made by a function using setState in React. I have in my constructor as follows:

this.state = {
    sources: []
};

This displays the correct array (I tested it with [0,1,2]). However, when I try to setState in a method like so:

this.setState({
    sources: [0,1,2]
})

it does not work and still displays the empty (or original) array. I understand you cannot mutate an array as state directly in React, but I don't think that's what I'm doing here. Here are some other things I have tried when researching this question, none of which have worked:

this.setState({
    sources: [...this.state.sources, 1]
})

...

this.setState({
    sources: this.state.sources.concat('test')
})

...

var temp = [0,1,2]
this.setState({
    sources: temp
})

Thanks in advance for any help!

EDIT Full code:

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

        this.state = {
            sources: [],
        };

        this.searchSources = this.searchSources.bind(this);
    }

    searchSources() {
    // commented out the actual method to replace with test code
        var temp=[0,1,2];
        console.log(temp); // [0,1,2] so I know the method works
        this.setState({
            sources: temp // etc for the other things i tried
        })
        console.log("this.state.sources: " + this.state.sources); // empty
    }

    render() {
        return(
        // etc...
          <button type="button" onClick={this.searchSources}>Test</button>
        );
    }
}
11
  • 1
    works here - codesandbox.io/s/l7j005yknz Commented Jul 17, 2018 at 14:15
  • 1
    It should not be this.state({ sources: [] }; in the constructor, but this.state = { sources: [] }; Commented Jul 17, 2018 at 14:17
  • Could you post a snippet of the method you are calling the setState from Commented Jul 17, 2018 at 14:21
  • @Tholle thank you, that was a typo in my question, in the actual code file I have it written correctly Commented Jul 17, 2018 at 14:21
  • Alright. Could you include your entire component that has this behavior? It's hard to say what might be wrong from the code currently in your question. Commented Jul 17, 2018 at 14:22

2 Answers 2

3

Your code is working, but you don't take into consideration that setState is asynchronous. If you log this.state in the callback that can be given as second argument to setState it will guarantee it has updated.

this.setState({ sources: temp }, () => {
  console.log(this.state.sources);
});
Sign up to request clarification or add additional context in comments.

3 Comments

We see the same question nearly everyday. Why does not people use render method to log the state? I hold myself from answering "Use the render method" instead of this callback one :)
@devserkan I fell for this myself back when I started using React. I think it's better now, but it's not all that obvious from the documentation that it is asynchronous.
Then, I'm the lucky one I guess :). Yes documentation is not so clear, I think I followed some good tutorials this is why I did not fell into this problem.
-2

Here is an example that should work as you describe:

class ArrayTest extends React.Component {

  constructor() {
    super();
    this.state = {
      sources: [],
    };
  }

  public render() {

    return (
      <div>
      <div>test: {this.state.sources}</div>
      <button onClick={this._changeValue}>test</button>
       </div>
    );
  }

  private _changeValue = () => this.setState( {sources: [1,5] } );  
}

ReactDOM.render( 
  <ArrayTest />,
  document.getElementById('content')
);

1 Comment

Is there public or private in JS classes?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.