React component not re-rendering on state change

后端 未结 7 798
抹茶落季
抹茶落季 2021-02-02 05:59

I have a React Class that\'s going to an API to get content. I\'ve confirmed the data is coming back, but it\'s not re-rendering:

var DealsList = React.createCla         


        
相关标签:
7条回答
  • 2021-02-02 06:37

    My issue was that I was using 'React.PureComponent' when I should have been using 'React.Component'.

    0 讨论(0)
  • 2021-02-02 06:42

    Another oh-so-easy mistake, which was the source of the problem for me: I’d written my own shouldComponentUpdate method, which didn’t check the new state change I’d added.

    0 讨论(0)
  • 2021-02-02 06:42

    After looking into many answers (most of them are correct for their scenarios) and none of them fix my problem I realized that my case is a bit different:

    In my weird scenario my component was being rendered inside the state and therefore couldn't be updated. Below is a simple example:

    constructor() {
        this.myMethod = this.myMethod.bind(this);
        this.changeTitle = this.changeTitle.bind(this);
    
        this.myMethod();
    }
    
    changeTitle() {
        this.setState({title: 'I will never get updated!!'});
    }
    
    myMethod() {
        this.setState({body: <div>{this.state.title}</div>});
    }
    
    render() {
        return <>
            {this.state.body}
            <Button onclick={() => this.changeTitle()}>Change Title!</Button>
        </>
    }
    

    After refactoring the code to not render the body from state it worked fine :)

    0 讨论(0)
  • 2021-02-02 06:43

    I'd like to add to this the enormously simple, but oh so easily made mistake of writing:

    this.state.something = 'changed';
    

    ... and then not understanding why it's not rendering and Googling and coming on this page, only to realize that you should have written:

    this.setState({something: 'changed'});
    

    React only triggers a re-render if you use setState to update the state.

    0 讨论(0)
  • 2021-02-02 06:53

    That's because the response from chrome.runtime.sendMessage is asynchronous; here's the order of operations:

    var newDeals = [];
    
    // (1) first chrome.runtime.sendMessage is called, and *registers a callback*
    // so that when the data comes back *in the future*
    // the function will be called
    chrome.runtime.sendMessage({...}, function(deals) {
      // (3) sometime in the future, this function runs,
      // but it's too late
      newDeals = deals;
    });
    
    // (2) this is called immediately, `newDeals` is an empty array
    this.setState({ deals: newDeals });
    

    When you pause the script with the debugger, you're giving the extension time to call the callback; by the time you continue, the data has arrived and it appears to work.

    To fix, you want to do the setState call after the data comes back from the Chrome extension:

    var newDeals = [];
    
    // (1) first chrome.runtime.sendMessage is called, and *registers a callback*
    // so that when the data comes back *in the future*
    // the function will be called
    chrome.runtime.sendMessage({...}, function(deals) {
      // (2) sometime in the future, this function runs
      newDeals = deals;
    
      // (3) now you can call `setState` with the data
      this.setState({ deals: newDeals });
    }.bind(this)); // Don't forget to bind(this) (or use an arrow function)
    

    [Edit]

    If this doesn't work for you, check out the other answers on this question, which explain other reasons your component might not be updating.

    0 讨论(0)
  • 2021-02-02 06:57

    In my case, I was calling this.setState({}) correctly, but I my function wasn't bound to this, so it wasn't working. Adding .bind(this) to the function call or doing this.foo = this.foo.bind(this) in the constructor fixed it.

    0 讨论(0)
提交回复
热议问题