React Hook:将数据从子组件发送到父组件

IT技术 reactjs react-hooks
2021-03-27 03:11:16

我正在寻找将数据从子组件传递到其父组件的最简单解决方案。

我听说过使用上下文、传递槽属性或更新props,但我不知道哪一个是最好的解决方案。

我正在构建一个管理界面,其中包含一个带有表的 ChildComponent 的 PageComponent,我可以在其中选择多行。我想将我在我的 ChildComponent 中选择的行数发送给我的父 PageComponent。

类似的东西:

页面组件:

<div className="App">
  <EnhancedTable />         
  <h2>count 0</h2>
  (count should be updated from child)
</div>

子组件:

 const EnhancedTable = () => {
     const [count, setCount] = useState(0);
     return (
       <button onClick={() => setCount(count + 1)}>
          Click me {count}
       </button>
     )
  };

我确定这是一件非常简单的事情,我不想为此使用 redux。

5个回答

针对这些情况的常用技术是将状态提升到所有需要使用该状态的组件的第一个共同祖先(即PageComponent本例中的 ),并将状态和状态更改函数作为props传递给子组件.

例子

const { useState } = React;

function PageComponent() {
  const [count, setCount] = useState(0);
  const increment = () => {
    setCount(count + 1)
  }

  return (
    <div className="App">
      <ChildComponent onClick={increment} count={count} />         
      <h2>count {count}</h2>
      (count should be updated from child)
    </div>
  );
}

const ChildComponent = ({ onClick, count }) => {
  return (
    <button onClick={onClick}>
       Click me {count}
    </button>
  )
};

ReactDOM.render(<PageComponent />, document.getElementById("root"));
<script src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>

<div id="root"></div>

是的,但我需要在 ChildComponent 中添加增量函数。然后用结果更新父级。
2021-05-27 03:11:16
谢谢你把我从 forwardRef 的恐怖中救了出来。它适用于我的项目。
2021-06-06 03:11:16
非常感谢。这真的帮助了我
2021-06-16 03:11:16
问题是如果我有 const increment (value) => { console.log(value) -> real value 我从 child c setState(value) console.log(state) -> undefined } 但是在第二个 callbackCall 之后我得到了上一个状态值。如何解决这个问题?
2021-06-17 03:11:16

您可以在父组件中创建一个方法,将其传递给子组件并在每次子组件的状态更改时从props中调用它,从而将状态保留在子组件中。

    const EnhancedTable = ({ parentCallback }) => {
        const [count, setCount] = useState(0);
        
        return (
            <button onClick={() => {
                const newValue = count + 1;
                setCount(newValue);
                parentCallback(newValue);
            }}>
                 Click me {count}
            </button>
        )
    };

    class PageComponent extends React.Component { 
        callback = (count) => {
            // do something with value in parent component, like save to state
        }

        render() {
            return (
                <div className="App">
                    <EnhancedTable parentCallback={this.callback} />         
                    <h2>count 0</h2>
                    (count should be updated from child)
                </div>
            )
        }
    }
但现在可能会this.callback触发不必要的重新渲染?
2021-05-29 03:11:16
@ecoe 当然可以,这取决于回调究竟做了什么。调用一些外部函数/调度动作应该是相对安全的,设置parent的状态——不是那么多。这绝对不是最干净的代码,因此如果可能,应采用其他答案的方法。
2021-06-18 03:11:16

为了让事情变得超级简单,您实际上可以将状态设置器共享给子项,现在他们可以访问设置其父项的状态。

示例:假设有如下 4 个组件,

function App() {
  return (
    <div className="App">
      <GrandParent />
    </div>
  );
}

const GrandParent = () => {
  const [name, setName] = useState("i'm Grand Parent");
  return (
    <>
      <div>{name}</div>
      <Parent setName={setName} />
    </>
  );
};

const Parent = params => {
  return (
    <>
      <button onClick={() => params.setName("i'm from Parent")}>
        from Parent
      </button>
      <Child setName={params.setName} />
    </>
  );
};

const Child = params => {
  return (
    <>
      <button onClick={() => params.setName("i'm from Child")}>
        from Child
      </button>
    </>
  );
};

因此祖父组件具有实际状态,并且通过将 setter 方法 (setName) 共享给父和子组件,他们可以访问更改祖父组件的状态。

您可以在下面的沙箱中找到工作代码, https://codesandbox.io/embed/async-fire-kl197

请提供链接中的基本详细信息,因为链接将来可能会过期。
2021-06-05 03:11:16
谢谢,这很有帮助。
2021-06-06 03:11:16

我必须在type script 中做到这一点面向对象方面需要开发人员在继承父级后将此回调方法添加为接口中的字段,并且此props的类型为Function我觉得这很酷!

我不得不处理类似的问题,并找到了另一种方法,使用对象来引用不同函数之间和同一文件中的状态。

import React, { useState } from "react";

let myState = {};

const GrandParent = () => {
  const [name, setName] = useState("i'm Grand Parent");
  myState.name=name;
  myState.setName=setName;
  return (
    <>
      <div>{name}</div>
      <Parent />
    </>
  );
};
export default GrandParent;

const Parent = () => {
  return (
    <>
      <button onClick={() => myState.setName("i'm from Parent")}>
        from Parent
      </button>
      <Child />
    </>
  );
};

const Child = () => {
  return (
    <>
      <button onClick={() => myState.setName("i'm from Child")}>
        from Child
      </button>
    </>
  );
};
我真的不确定这是否是使用 useState 的正确方法。我建议密切关注官方文档(reactjs.org/docs/hooks-state.html)。在上面的答案中,您不需要“myState”,您可以只使用 useState 中的 name 和 setName 变量。试想一下,如果您想获得一个变量值,即“名称”,请使用第一个变量。如果要设置变量,请使用第二个变量,即 setName。公平竞争,尝试提出自己的解决方案的好工作,但有时它会以一团糟结束。坚持最佳实践和官方文档。
2021-06-06 03:11:16