【问题标题】:Update Props of Component in Array更新数组中组件的 Props
【发布时间】:2021-06-20 01:52:07
【问题描述】:

我有一个包含组件数组的组件,但数组中的组件似乎没有改变它的 props。

这是父级的简化示例:

const MyParent = () => {
  const [foo, setFoo] = useState();
  const [viewStack, setViewStack] = useState([]);

  const handleDataChange = (newData) => {
    const newData = {
      ...foo,
      newData,
    }

    setFoo(newData);
  }

  const handleNextButton(key) {
    const currentViewStack = viewStack;
    switch(key) {
      (... several other cases here)
      case theValueWeWant:
        currentViewStack.push(<MyChildComponent myData={foo} dataChangeHandler={handleDataChange} />);
        break;
    }

    setViewStack(currentViewStack);
  }

  return ({viewStack[viewStack.length - 1]});
  
}

这是一个简化的孩子的例子:

const MyChildComponent = (props) => {
  const [bar, setBar] = useState();

  useEffect(() => {
    setBar(props.myData);
  }, [props.myData]);
  
  return (
    <div>
      {bar}
      <button onClick={() => { props.dataChangeHandler('my new value'); }}>Click me</button>
    </div>
  );
};

值得注意的是MyChildComponent确实有孩子,但是当我在MyChildComponent中放一个useEffect时,当道具改变时它不会触发。 (此外,我们使用数组来存储我们的组件,因为用户在工作流中进行,因此handleClickNextButton)。这是code sandbox

问题是,当我更改 MyChildComponent 的子组件中的数据时,我将新数据传递给父组件并且状态发生了更改,但子组件没有接收到新数据。我有预感为什么,但我不喜欢这个解决方案,我在这里发帖看看我是否遗漏了什么(希望能找到更好的解决方案)。

我认为问题在于我希望更改子组件的道具,因为我传入了一个状态变量。它没有改变的原因是因为它在一个数组中(顺便说一句,我确实尝试向数组中的元素添加关键道具,但这并没有解决问题)。一种解决方案是在每次该值更改时重建数组。我不喜欢这个有两个原因:

  1. 每次重新渲染时重建数组似乎效率很低
  2. 这是反直觉的。我希望它的行为有点像 lambda,我可以访问定义 lambda 的范围内的变量(即,您在 lambda 中获得像 foo 这样的全局变量)。我想在构建数组时“设置”这些值是有道理的,但我想知道是否有人可以提供一个技术原因,为什么这是不可能的。

谢谢你:)

【问题讨论】:

    标签: javascript reactjs react-hooks


    【解决方案1】:

    您认为问题在于您的数组状态是正确的。正如this related question 中提到的,您需要将反应状态对象视为不可变。由于在您的代码中,您直接使用.push() 修改数组,因此状态对象没有正确更新。

    这里的关键是,每当您更新以 React 状态存储的对象或数组时,您需要在设置新状态之前创建一个全新的对象或数组。 p>

    例如:

    // === arrays ===
    const [nums, setNums] = useState([])
    
    // ...some code
    
    const newNumToAddToList = 3
    setNums([ ...nums, newNumToAddToList ])
    // ===============
    
    // === objects ===
    const [data, setData] = useState({ initialProp: 3 })
    
    // ...some code
    
    const newDataProperty = 'a string value'
    setData({ ...data, newProp: newDataProperty })
    
    // or...
    const newInitialPropValue = 29
    setData({ initialProp: newInitialPropValue })
    

    附带说明,我强烈建议您不要将 react 组件存储在 state 中。实现目标的一种更简洁的方法可能是将基础数据存储在状态中 - 您的代码框示例中的labels。然后,您可以将这些标签映射到 render 方法中的组件中。这是example in codesandbox

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-03-18
      • 2015-08-24
      • 2019-06-11
      • 2018-08-31
      • 2018-06-08
      • 1970-01-01
      • 2019-09-11
      相关资源
      最近更新 更多