父组件状态改变,子组件不重新渲染

Posted

技术标签:

【中文标题】父组件状态改变,子组件不重新渲染【英文标题】:State changed in parent component, child components do not re-render 【发布时间】:2020-12-30 11:50:24 【问题描述】:

我正在构建一个 whack-a-mole 应用程序,并且我有一个组件:

渲染每个row 生成一个随机数,即index 指向鼹鼠从哪个洞中弹出

这会每行生成 5 个孔,带有随机生成索引的孔会得到一个布尔值来标记它是否有痣。

mole被点击时;

它调用一个函数来通过分配一个新的随机数来改变Row 组件的状态。 console.log() 表明它确实重新生成了一个随机数,并且与每个 Hole 组件映射的变量也接收新的、更新的 Hole 组件,其新索引具有 mole

挑战 初始渲染效果很好。鼹鼠被放置在随机孔中,点击时鼹鼠消失。

但是,mole 不会出现在新索引中,hole 组件也不会重新渲染,因为这些组件 console.log()s 都不会出现。

即使更改了父状态,并且重新渲染了 holes 集合的新道具,为什么 Hole 组件从未真正运行过?

更改孔号的方法在Row组件中,保存新组件的编号和变量也在其中。

所以我想问题可能出在 Hole 组件的某个地方。

class Rows extends Component
    
    state =  holeNum: null  ;

    componentWillMount() 
       this.changeSpot();
    ;

    changeSpot = () => 
       // console.log(this.state.holeNum);
       let random = Math.floor(Math.random() * Math.floor(5));
       this.setState( holeNum: random );
       // console.log("Spot changed ", this.state.holeNum, random)
    

    render()         
       // console.log("ROW ", this.props.id)
       let holes = [0,1,2,3,4];
       // console.log(this.state.holeNum)
       let row = holes.map(idx => 
          // if holeNum is equal to index has mole is true
          // console.log("rerendering")
          let moleRender = false;
          if(this.state.holeNum === idx)
              moleRender = true;
              // console.log(idx, moleRender, this.state.holeNum)            
          ;
            
          return (
            <Hole
               changeSpot=this.changeSpot
               updateScore=this.props.updateScore
               hasMole=moleRender
            />
          );
       );

       // console.log(row)

       return (
          <div className="Row">
             row
          </div>
       );
    ;
;

这里是Hole 组件

class Hole extends Component
    
    state =  hasMole: false ;

    componentWillMount()
       // console.log("Comp will mount Hole")
       if(this.props.hasMole===true)
          // console.log(this.props.hasMole)
          this.setState(hasMole:true);
       ;
    ;

    moleClickedHandler = () => 
       this.setState( hasMole:false );
       // this.props.updateScore()
       this.props.changeSpot();
    ;
    
    render() 
       let mole = null;
       if(this.state.hasMole === true)
           // console.log(this.state.hasMole)
           mole = <Mole clicked=this.moleClickedHandler />;
       ;

       return (
           <div className="Hole">
              mole
           </div>
       );
    ;
;

谢谢!

【问题讨论】:

您是否收到任何有关缺少 key 属性的控制台警告?如果您使用 .map 生成组件,我想 React 会希望它跟踪它们——这可能与您看到的问题有关...... 我添加了键并玩弄了一些东西,我意识到问题在于子组件 的生命周期。 setState 的“hasMole”属性仅在安装孔时才变为真。感谢您的回复 【参考方案1】:

我猜您在开发者工具的控制台中收到与缺少“关键”道具有关的警告 您可以在此处了解更多为什么需要密钥:https://reactjs.org/docs/lists-and-keys.html

你可以通过添加密钥来解决这个问题

         <Hole
            key=ix
            changeSpot=this.changeSpot
            updateScore=this.props.updateScore
            hasMole=moleRender/>

【讨论】:

以上是关于父组件状态改变,子组件不重新渲染的主要内容,如果未能解决你的问题,请参考以下文章

React性能优化之减少组件渲染次数

React Native - 从父组件重新渲染子组件

React 啥时候重新渲染子组件?

在父组件的状态更改中重新呈现子组件

反应:孩子点击改变父母的状态以重新渲染

子组件不会重新渲染,但父组件会重新渲染。如何让子组件重新渲染?