【问题标题】:useState passed from parent to child and used in child doesn't trigger the re-render of the childuseState 从父级传递给子级并在子级中使用不会触发子级的重新渲染
【发布时间】:2021-03-08 05:37:40
【问题描述】:

所以,我猜想当 useState 更新时,父组件不会重新渲染子组件。 但是组件应该在使用 useState 时自动重新渲染,对吗? 或者我错过了什么......

index.js

import { useEffect, useState, useRef } from "react";

import Clicking from "./clicking";

export default function IndexPage() {
  const parentBtn = useRef(null);

  const [clicks, setClicks] = useState(0);

  useEffect(() => {
    console.log("Clicks: ", clicks);

    if (null !== parentBtn.current) {
      parentBtn.current.addEventListener("click", () => setClicks(clicks + 1));
    }
  }, [clicks]);

  return (
    <div>
      <p>Clicks number : {clicks}</p>
      <Clicking clicks={clicks} setClicks={setClicks} />
      <button ref={parentBtn}>Parent button</button>
    </div>
  );
}

clicking.js

import { useEffect, useRef } from "react";

const Clicking = ({ clicks, setClicks }) => {
  const childBtn = useRef(null);

  useEffect(() => {
    childBtn.current.addEventListener("click", () => setClicks(clicks + 1));
  }, []);

  return <button ref={childBtn}>Child button</button>;
};

export default Clicking;

有人知道怎么解决吗?

这里是案例的代码框:https://codesandbox.io/s/pensive-sun-9993d

感谢您的帮助!

【问题讨论】:

    标签: reactjs components rendering next.js use-state


    【解决方案1】:

    问题是您的useEffect 只运行一次,因此只接收clicks 的初始值。
    您需要做的是停止将 clicks 值传递给孩子,而只需从 setClicks 函数中获取状态值,因为无论如何您的更新都取决于之前的状态值。

    您还应该将setClicks 作为依赖项传递给useEffect,尽管在这种情况下它在技术上不是强制性的,因为该函数已被记忆,因此永远不会改变,但这是最佳实践,您将避免如果你这样做,未来。

    但是无论如何,孩子中的useEffect 在您的情况下是无用的,您最好将onClick 道具传递给孩子,这将触发父母的功能以在单击按钮时更新计数器。 父母也是如此,您可以简单地使用 onClick 属性而不是使用 useRef 并最终得到这个更简单的代码:

    index.js

    import { useState } from "react";
    
    import Clicking from "./clicking";
    
    export default function IndexPage() {
      const [clicks, setClicks] = useState(0);
    
      const updateClicksCounter = () => {
        setClicks(clicks => clicks + 1);
      };
    
      return (
        <div>
          <p>Clicks number : {clicks}</p>
          <Clicking onClick={updateClicksCounter} />
          <button onClick={updateClicksCounter}>Parent button</button>
        </div>
      );
    }
    

    clicking.js

    const Clicking = ({ onClick }) => {
      return <button onClick={onClick}>Child button</button>;
    };
    
    export default Clicking;
    

    【讨论】:

    • 好的,谢谢@Valentin,所以现在它正确更新了clicks var,但是如果我想在孩子中显示clicks var,我怎样才能获得更新的状态?现在,如果我将 clicks 传递给孩子并 console.log 它,它总是显示它的初始值。
    • @Maël 如果您将它作为道具传递,您可以简单地使用{clicks} 在返回中显示它。如果您想在useEffect 中使用该值,则需要将其作为参数传递,以便每次参数更新时都会运行useEffect(() =&gt; { console.log("clicks", clicks) }, [clicks])
    • 好的,我试图在 useEffect 之外使用它,所以它没有与 react 同步。谢谢!
    【解决方案2】:

    我在使用setClicks的孩子身上找到了解决方案

    我换了

    setClicks(clicks + 1)
    

    通过

    setClicks(val => val + 1)
    

    而且它有效。 也许有人对反应生命周期有解释?

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-03-06
    • 2021-12-26
    • 2020-12-31
    • 2017-09-15
    • 1970-01-01
    • 2021-06-29
    • 2021-06-29
    • 1970-01-01
    相关资源
    最近更新 更多