简体   繁体   English

通过带有钩子的道具更新状态

[英]Updating State Through props with hooks

I am trying to update the state of something on a click from a component by lifting up the state and passing it as a prop into the other component and trying to update it.我试图通过提升状态并将其作为道具传递给另一个组件并尝试更新它来更新组件的单击状态。

this is the App.js这是 App.js

function App() {
  const [currentConfig, setCurrentConfig] = useState(0);
  const availableConfigs = [
    { id: 1, name: "Config 1", number: 1, key: 1 },
    { id: 2, name: "Config 2", number: 2, key: 2 },
    { id: 3, name: "Config 3", key: 3 },
    { id: 4, name: "Config 4", key: 4 },
    { id: 5, name: "Config 5", key: 5 },
    { id: 6, name: "Config 6", key: 6 },
    { id: 7, name: "Config 7", key: 7 },
  ];

  const [configs, setConfigs] = useState(availableConfigs);

  //function undoConfigAnimation(currentConfig) {}

  return (
    <div>
      <Tree
        configs={configs}
        animateConfigs={startConfigAnimation}
        setConfig={setCurrentConfig}
        currentConfig={currentConfig}
      />
      <NavBar />
    </div>
  );

  function startConfigAnimation(configClicked) {
    console.log(currentConfig);
    configs.forEach((config) => {
      if (configClicked !== config.name) {
        var elm = document.getElementById(config.name);
        elm.style.transform = "translate(-200px)";
        setTimeout(() => (elm.style.transform = "rotateZ(180deg)"), 1000);
      }
    });
  }
}

export default App;

this is the component这是组件

function Tree(props) {
  return (
    <div class="treeContainer">
      {props.configs.map((config) => {
        return (
          <div
            id={config.name}
            class="container1"
            onClick={() => {
              props.setConfig(config.name);

              props.animateConfigs(config.name);
              if (props.currentConfig !== config.name) {
                props.setConfig.bind(config.name);
              }
            }}
          >
            <Configs configNumber={config.number} configName={config.name} />
          </div>
        );
      })}
    </div>
  );
}
export default Tree;

currently, it does update the state, but it only updates it to the state before the click so an example output if the currentConfig === 0 would be as follows当前,它会更新状态,但它只会将其更新为单击前的状态,因此如果 currentConfig === 0 将如下所示,示例输出

click config 1 currentConfig = 0 click config 2 currentConfig = "config 1"单击配置 1 currentConfig = 0 单击配置 2 currentConfig = "配置 1"

Since the setState is async, the console.log will always be one behind.由于 setState 是异步的,console.log 将始终落后。 This does not mean that the state is not updated, but only not displayed in the console or yet available in the function.这并不意味着状态没有更新,只是没有显示在控制台中或在函数中可用。

So the flow would be:所以流程是:

  1. You dispatch the change.您发送更改。
  2. You call startConfigAnimation , but it is still in sync, so that currentConfig is still the previous value.您调用startConfigAnimation ,但它仍处于同步状态,因此currentConfig仍然是先前的值。
  3. The state is updated with the new value.使用新值更新状态。

There are 2 ways to fix this:有两种方法可以解决这个问题:

  1. Use a useEffect: Listen to the currentConfig with a useEffect and trigger the animation, if the config changes.使用 useEffect:使用 useEffect 监听currentConfig并在配置更改时触发动画。
React.useEffect(() => startConfigAnimation(currentConfig), [currentConfig])
  1. You are already passing the new/updated config to startConfigAnimation so you could be using that.您已经将新的/更新的配置传递给startConfigAnimation因此您可以使用它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM