【问题标题】:setState() does not trigger re-rendersetState() 不会触发重新渲染
【发布时间】:2021-07-27 11:59:31
【问题描述】:

尽管试图避免所有记录在案的陷阱,这些陷阱会阻止 React 在状态更改后重新渲染,但我仍然无法找出我的问题:

// Grid.js, render a grid of random-colored boxes

constructor(props){
        super(props); 
         this.initialcolors = this.initialcolors.bind(this); 
         this.updatecolors = this.updatecolors.bind(this);  
         this.state = {colors: this.initialcolors()}
    }

// ...

    updatecolors(index){
    let currentColors = [...this.state.colors];
    let currentColor = currentColors[index];
    let newColors = this.props.colors.filter(c => c !== currentColor)
    let newColor = newColors[Math.floor(Math.random() * newColors.length)];
    currentColors[index]=newColor; 
    this.setState(st => ({colors: currentColors}))
}

render(){
     return(<div>
           {this.state.colors.map( (color, index) => 
              <Box key={index} position={index} color={color} updatefunc={this.updatecolors} className="Box.css"/>
           )}
            </div>)
}

// Box.js, the colored box, onClick triggers state-change by calling updatefunc from parent

constructor(props){
    super(props);
    this.state = {color: this.props.color}; 
    this.changeColor = this.changeColor.bind(this); 
}

changeColor(evt){
    this.props.updatefunc(this.props.position); 
}

render(){
    return(
    <div style={{backgroundColor: this.state.color, 
                 height: 100, 
                 width: 100, 
                 padding: 0.5}} 
         onClick={this.changeColor}> </div>
    )
}

}

从每个盒子组件调用更新函数并触发在盒子网格上分配新颜色。

尽量避免常见的错误:

  • 颜色数组仅在通过扩展运算符从状态复制后才被修改
  • 新数组通过 setState() 传递
  • 此外,我负责两个组件中函数的实例绑定

然而,尽管 onClick 成功触发了状态改变,但并没有发生重新渲染。我在这里缺少的其他方面是什么?

非常感谢!

【问题讨论】:

  • 在组件中直接将 props 赋值给 state 是不好的。
  • 是的,但是对于仅分配道具结构的单个部分也是如此: this.state = {color: this.props.color}; ?

标签: reactjs


【解决方案1】:

Box.js 使用this.state.color 作为背景颜色,它永远不会改变,因为每个盒子只调用一次构造函数。你可能想使用 this.props.color ,它的颜色从 Grid 改变了。

class Box extends Component {
  constructor () {
    super();
    this.changeColor = this.changeColor.bind(this); 
  }

  changeColor (evt) {
    this.props.updatefunc(this.props.position); 
  }

  render () {
    return (
      <div
        style={{
          backgroundColor: this.props.color, 
          height: 100, 
          width: 100, 
          padding: 0.5
        }} 
        onClick={this.changeColor}
      />
    )
  }
}

【讨论】:

  • 是的,这是有道理的:onClick 触发父状态更改 -> 通过 map 函数使用更新的道具重新渲染 -> 新颜色进入每个子组件的道具,构造函数保持不变。
猜你喜欢
  • 1970-01-01
  • 2015-06-10
  • 1970-01-01
  • 2022-01-06
  • 2021-08-04
  • 2017-06-09
  • 1970-01-01
  • 2016-10-20
  • 2019-01-24
相关资源
最近更新 更多