【问题标题】:ReactJS: Change state of child componentReactJS:更改子组件的状态
【发布时间】:2020-06-06 00:16:04
【问题描述】:

我有父组件,它在其状态中包含一个全局值。此值的更改必须触发子组件的状态更改,如下例所示:

function Parent(props) {
const [parentState, setParentState] = useState(someState);

return (
  <button onClick={() => setParentState(newState)>Button</button>
  <ChildComponent parentState={parentState} />
}

function Child(props) {
const [childState, setChildState] = useState(getState(props.parentState));
}

点击本例中的按钮应该会触发 Child 组件中状态的非平凡变化(它使用 parentState 作为参数来生成自己的状态)。

我想这个问题的第一个答案是提升状态 - 但是我不想这样做,因为通过 .map 函数生成了许多 Child - 我需要将它们的状态保留在一个数组中并将其传播到所有子组件。父组件中的值是与所有子组件相关的全局值,并且当 parentState 发生变化时,所有子组件都必须更改其状态。

有没有什么好的方法可以在不提升子组件状态的情况下实现这一目标?我希望我已经足够好地描述了这个问题 - 如果没有,我很乐意更新信息。

【问题讨论】:

  • 您能否详细说明一下父级的全局值是如何应用于子级的?您是否将整个parentState 应用于孩子?如果是这样,孩子们甚至需要自己的状态吗?我认为您的问题暗示父母会根据需要“重置”孩子,但是孩子可能会偏离父母并在状态上有所不同,直到父母的下一次“重置”将孩子恢复为与父母相同.我在正确的轨道上吗?
  • Aurélien:我已经将父母的状态转移给孩子,问题是孩子的状态是在初始化时设置的(请参阅孩子状态)并且不会随着父母状态的后续变化而改变。 @WGriffing:孩子根据父母的状态(比如用户的全局设置)和它自己的非衍生状态(组件的设置)加载一组数据。这两个因素作为返回子数据的函数的参数传递。

标签: javascript reactjs state


【解决方案1】:

根据您的澄清评论,这里有一些关于如何继续的想法。根据parentState 对象包含的内容,可能会有更好的方法来做到这一点,但希望它会有助于激发一些想法。

  1. 以两种方式使用parentState。
    1. 作为Child 道具。每当Parent 更改其值时,这将始终更新。
    2. 作为Child 的useState 挂钩之一的初始值。这将初始化孩子的派生状态,但将允许Child 状态根据Child 组件内的用户操作随时间而偏离。
  2. 当parentState 变量发生变化或childStateSettings 变量发生变化时,使用useEffect 钩子触发您的Child getData 函数。
  3. 在Child 中使用多个useState 挂钩将状态的非衍生部分与Child 状态的继承/衍生部分分开。对于导数状态childStateSettings,使用parentState作为初始值。

所以Child 变成这样:

import { useEffect, useState } from 'react';

function Child(props) {
  const { parentState } = props;

  // initial value of child settings from parent
  const [childStateSettings, setChildStateSettings] = useState(parentState); 

  // non-inherited/non-derivative state of child
  const [childStateData, setChildStateData] = useState({}); 

  // Depending on the number of settings and ways in which
  //  the user can make them different than the parent/global settings,
  //  you may want to have even more useState hooks to further separate
  //  the settings into individual pieces. I think this would simplify
  //  your various `onChange`/`onSelection'/etc. function logic, but I
  //  couldn't say for certain without more details.


  useEffect(() => {
    getData(childStateDerivative, childStateNonDerivative);
  }, [parentState, childStateSettings]};

  // pseudocode invented by me as a guess of 
  //  how you might need to use things based on your comment
  const getData = (parentState, childState) => {
    // last spread object takes precedence if duplicate keys are present in both objects
    const combinedState = { ...parentState, ...childState }; 
    API.get('http://some_path', combinedState).then(data => {
      setChildStateData(data);
    });
  };

  // you'll probably draw some inputs so that the 
  //  user can alter the child's state settings but
  //  I didn't bother trying to guess what that might look like.
  return (<>...</>); 

}

【讨论】:

    【解决方案2】:

    孩子不应该有自己的状态。它应该完全取决于父状态/道具。

    function Parent(props) {
    const [parentState, setParentState] = useState(someState);
    
    return (
      <button onClick={() => setParentState(newState)>Button</button>
      <ChildComponent parentState={parentState} />
    }
    
    function Child(props) {
    }
    

    【讨论】:

      【解决方案3】:

      当您更改父状态时,子状态将重绘。您可以在构造函数中使用 setState() 在 DOM 中重新创建子状态时对其进行修改。

      【讨论】:

      • 也许我遗漏了一些东西,但孩子的数据没有改变。我正在使用 useState,它在初始化时设置数据,但我看不到任何事后触发它的方法。即使我将状态传递给子组件,父组件的状态更改后子组件也不会更改其状态。
      • 按钮点击时状态应该改变吗? useState 有 2 个成员:状态变量和用于更改该变量的回调挂钩。除此之外,我们还需要查看子组件的代码。如果没有这两个组件的完整代码,我无法告诉你更多。
      猜你喜欢
      • 2021-06-08
      • 1970-01-01
      • 2017-11-05
      • 2015-04-15
      • 2016-10-02
      • 1970-01-01
      • 1970-01-01
      • 2018-07-08
      • 2021-01-21
      相关资源
      最近更新 更多