admin管理员组

文章数量:1317131

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
        });
      }

本文标签: javascriptReact setState not rerenderingStack Overflow