首页 > 解决方案 > 为什么我在另一个组件中更改了状态后该功能不起作用?

问题描述

这些是我正在使用的三个组件,不包括在 DOM 中显示它们的组件,但这不是必需的。

这里我有一个父组件和两个子组件。

由于某种原因,当弹出窗口处于活动状态时,我单击Refresh Child 1 Component按钮,它会将状态更改回Child1,但我失去了该组件中的功能。因此该popUpToggle功能停止工作。

它以前工作正常。但是,当我再次单击Refresh Child 1 Component时,它开始工作。这是为什么?

import React, { useState, useEffect } from 'react';
import Child1 from './child1'
import Child2 from './child2'

const Parent = () => {
  const [display, setDisplay] = useState('');
  const [popUp, setPopUp] = useState(false);
  const [renderCount, setRenderCount] = useState(0);

  const popUpToggle = () => {
     setPopUp(!popUp)
     console.log('PopUp Toggle ran')
  };

  const reRenderComponent= () => {
     setRenderCount(renderCount + 1);
     setDisplay(
       <Child1 
         key={renderCount} 
         popUpToggle={popUpToggle} 
         renderCount={renderCount}
       />
     );
     popUpToggle();
     console.log('reRenderComponent ran, and the key is ' + renderCount)
  };
    
  useEffect(() => {
     setDisplay(
       <Child1 
         key={renderCount} 
         popUpToggle={popUpToggle} 
         renderCount={renderCount}
       />
     );
  }, [])

  return ( 
    <div>
      <button 
        style={{position: 'fixed', zIndex: '999', right: '0'}} 
        onClick={reRenderComponent}
      >
        Refresh Child 1 Component
      </button>
      {popUp ? <Child2 popUpToggle={popUpToggle}/> : null}
      {display}
    </div>
  );
};

export default Parent;

孩子 1:

import React from 'react';

const Child1 = ({ popUpToggle, renderCount }) => {    
  return ( 
    <>
      <button onClick={popUpToggle}>
        Pop Up Toggle function
      </button>
      <h1>Child 1 is up, count is {renderCount}</h1>
    </>
  );
};

export default Child1;

孩子 2:

import React, { useState } from 'react';

const Child2 = ({ popUpToggle }) => {   
  return ( 
    <div 
      style={{
        backgroundColor: 'rgba(0,0,0, .7)',
        width: '100vw',
        height: '100vh',
        margin: '0',
      }}
    >
      <h1>Child 2 is up</h1>
      <h2>PopUp active</h2>
      <button onClick={popUpToggle}>Toggle Pop Up</button>
    </div>
  );
};

export default Child2;

标签: reactjsjsx

解决方案


setDisplay(<Child1 /*etc*/ />);

将元素放入状态通常不是一个好主意。它很容易导致与您所看到的完全相同的错误。除非您明确这样做,否则状态中的元素永远不会更新,因此它可以轻松引用过时的数据。在您的情况下,我认为问题在于子组件具有对 的陈旧引用,而后者又在其闭包popUpToggle中有一个旧实例。popUp

更好的方法和标准方法是让您的状态只包含最少的数据。渲染时根据数据创建元素。这样,元素始终与最新数据同步。

在您的情况下,看起来所有数据都已经存在,因此我们不需要添加任何新的状态变量:

const Parent = () => {
  const [popUp, setPopUp] = useState(false);
  const [renderCount, setRenderCount] = useState(0);

  const popUpToggle = () => {
    setPopUp(prev => !prev);
  };

  const reRenderComponent = () => {
    setRenderCount(prev => prev + 1);
    popUpToggle();
  };

  return (
    <div>
      <button
        style={{ position: "fixed", zIndex: "999", right: "0" }}
        onClick={reRenderComponent}
      >
        Refresh Child 1 Component
      </button>
      {popUp && <Child2 popUpToggle={popUpToggle} />}
      <Child1
        key={renderCount}
        popUpToggle={popUpToggle}
        renderCount={renderCount}
      />
    </div>
  );
};


推荐阅读