最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - React setState not re-rendering - Stack Overflow

programmeradmin2浏览0评论

In below code, state of Test is updating but its not re-rendering. I have updated the state of parent on button click on change of which I expected it to rerender the whole ponent including Button. But its not re-rendering Button. Need help wrt this. This is a test code and both classes are necessary.

import React from 'react';

class Button extends React.Component {
  constructor(props){
      super(props)
      this.state = {
          id : props.id
      }
  }
  render() {
      console.log('Button state id is', this.state.id)
      return(
          <div>
              'hi ' +  {this.state.id}
              <br/>
              <button type='submit' onClick={this.props.handleSubmit}>
                  submit
              </button>
          </div>
      )
  }
}

export default class App extends React.Component {
  constructor(props) {
      super(props)
      this.state = {
          id: 1
      }
      this.changeId = this.changeId.bind(this)
  }
  changeId() {
      let id = this.state.id
      console.log('parent state id is', id)
      this.setState({
          id: ++id
      })
  }
  render() {
      return(
          <Button id={this.state.id} handleSubmit={this.changeId}/>
      )
  }
}

EDIT: I have modified the code to remove obvious errors like not passing in changeId function to Button

EDIT 2: Found the solution here: React Child Component Not Updating After Parent State Change ponentWillReceiveProps

In below code, state of Test is updating but its not re-rendering. I have updated the state of parent on button click on change of which I expected it to rerender the whole ponent including Button. But its not re-rendering Button. Need help wrt this. This is a test code and both classes are necessary.

import React from 'react';

class Button extends React.Component {
  constructor(props){
      super(props)
      this.state = {
          id : props.id
      }
  }
  render() {
      console.log('Button state id is', this.state.id)
      return(
          <div>
              'hi ' +  {this.state.id}
              <br/>
              <button type='submit' onClick={this.props.handleSubmit}>
                  submit
              </button>
          </div>
      )
  }
}

export default class App extends React.Component {
  constructor(props) {
      super(props)
      this.state = {
          id: 1
      }
      this.changeId = this.changeId.bind(this)
  }
  changeId() {
      let id = this.state.id
      console.log('parent state id is', id)
      this.setState({
          id: ++id
      })
  }
  render() {
      return(
          <Button id={this.state.id} handleSubmit={this.changeId}/>
      )
  }
}

EDIT: I have modified the code to remove obvious errors like not passing in changeId function to Button

EDIT 2: Found the solution here: React Child Component Not Updating After Parent State Change ponentWillReceiveProps

Share Improve this question edited Aug 6, 2019 at 8:03 xploreraj asked Aug 6, 2019 at 6:22 xplorerajxploreraj 4,36213 gold badges45 silver badges59 bronze badges 7
  • where is this id id={id} – cuongtd Commented Aug 6, 2019 at 6:27
  • Did you forget passing handleSubmit={this.changeId} to your <Button> ponent in render if Test ponent? And I think it should be {this.state.id} not just {id} – G_S Commented Aug 6, 2019 at 6:30
  • id is not defined in changeId() – Siddhartha Chowdhury Commented Aug 6, 2019 at 6:31
  • May not be related to answering this question but worth mentioning here. @xploreraj, this is why I like using TypeScript along with React. It is much clearer as to what is there in our Props. You define props as an interface and declare the properties it is going to have. Same is the case with state. – Raja Malik Commented Aug 6, 2019 at 6:40
  • yes, this is just code for this question, it should be this.state.id – xploreraj Commented Aug 6, 2019 at 7:12
 |  Show 2 more ments

4 Answers 4

Reset to default 3

For a number to re render in the child ponent you need to make following changes to your code:

In current scenario value of id in changeId function is event, so you can't do ++id. You have to update it to:

changeId() {
    this.setState({
        id: ++this.state.id
    })
}

and for child ponent to re render the props value, you have to listen if there is any change in props. For that use ponentDidUpdate lifecycle of react. Like this:

ponentDidUpdate(prevProps){
   if (this.props.id !== prevProps.id) {
    this.setState({id: this.props.id});
  }
}

The other way is don't store props.id in child state. Use it directly in render.

class Button extends React.Component {

  render() {
      return(
          <div>
              'hi ' +  {this.props.id}
              <br/>
              <button type='submit' onClick={this.props.handleSubmit}>
                  submit
              </button>
          </div>
      )
    }
}

class App extends React.Component {
  constructor(props) {
      super(props)
      this.state = {
          id: 1
      }
      this.changeId = this.changeId.bind(this)
  }
  changeId() {
      this.setState({
          id: ++this.state.id
      })
  }
  render() {
      return(
          <Button id={this.state.id} handleSubmit={this.changeId}/>
      )
    }
}

ReactDOM.render(<App />, document.getElementById('root'))
<script src="https://cdnjs.cloudflare./ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare./ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="root" />

You haven't actually passed handleSubmit as a prop to the Button ponent. Assuming you want changeId() to be called when you click the button, try this:

class Test extends React.Component {
    constructor(props) {
        super(props)
        this.state = {
            id: 1
        }
        this.changeId = this.changeId.bind(this)
    }
    changeId() {
        console.log('change id called', id)
        this.setState({
            id: ++id
        })
    }
    render() {
        return(
            <Button id={id} handleSubmit={this.changeId}/>
        )
    }
}

We can further optimise the ponent by doing something like this -: Highlights -:

  • changeId() { changed to changeId = () => { (fat arrow notation), if we use this we don't need this.changeId = this.changeId.bind(this);
  • Don't really need another ponent specially for button, can bine it in same ponent.
import React, {Component} from 'react'; 
export default class Test extends React.Component {
        constructor(props) {
            super(props)
            this.state = {
                id: 1
            }
        }
        changeId = () => {
            this.setState({
                id: ++this.state.id
            })
        }
        render() {
            return(
               <div>
                    'hi ' +  {this.state.id}
                    <br/>
                    <button type='submit' onClick={this.changeId}>
                        submit
                    </button>
                </div>
            )
        } }

The example for ponentWillReceiveProps worked in my case, when I wanted to update child ponent of React on setState of parent ponent:

      ponentWillReceiveProps(props) {
        this.setState({
          currentID: props.currentID
        });
      }
发布评论

评论列表(0)

  1. 暂无评论