反应setState不重新渲染

时间:2019-08-06 06:22:59

标签: javascript reactjs

在下面的代码中,测试状态正在更新,但未重新呈现。我已经更新了按钮更改时单击父按钮的状态,我希望它能重新渲染包括按钮在内的整个组件。但是它没有重新渲染Button。需要帮助。这是测试代码,并且两个类都是必需的

import pandas as pd
import numpy as np
df = pd.DataFrame({'Col1' : ['Bob', 'Joe', 'Bill', 'Mary', 'Joe'],
              'Col2' : ['Joe', 'Steve', 'Bob', 'Bob', 'Steve'],
               'Col3' : np.random.random(5)})
df['C12'] = df['Col1'] + df['Col2']
df

编辑:我已经修改了代码,以消除一些明显的错误,例如未将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}/> ) } } 函数传递给changeId

编辑2:在此处找到解决方案:React Child Component Not Updating After Parent State Change Button

4 个答案:

答案 0 :(得分:1)

要在子组件中重新显示数字,您需要对代码进行以下更改:

在当前情况下,changeId函数中id的值是event,所以您不能执行++ id。您必须将其更新为:

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

,并且要使子组件重新呈现props值,必须侦听props是否有任何更改。为此,使用react的componentDidUpdate生命周期。像这样:

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

另一种方法是不要在子状态下存储props.id。直接在渲染中使用它。

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.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="root" />

答案 1 :(得分:0)

您实际上并没有将handleSubmit作为对Button组件的支持。假设您希望在单击按钮时调用changeId(),请尝试以下操作:

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

答案 2 :(得分:0)

我们可以通过执行以下操作来进一步优化组件: 亮点-:

  • changeId() {更改为changeId = () => {(胖箭头表示法),如果我们使用它,则不需要this.changeId = this.changeId.bind(this);
  • 确实不需要按钮专用的其他组件,可以将其组合到同一组件中。
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>
            )
        } }

答案 3 :(得分:0)

componentWillReceiveProps 的示例适用于我的情况,当我想在父组件的 setState 上更新 React 的子组件时:

      componentWillReceiveProps(props) {
        this.setState({
          currentID: props.currentID
        });
      }