【问题标题】:React Hook : Send data from child to parent componentReact Hook:将数据从子组件发送到父组件
【发布时间】:2019-09-07 15:52:06
【问题描述】:

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

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

我正在构建一个管理界面,其中一个 PageComponent 包含一个 ChildComponent 和一个表格,我可以在其中选择多行。我想将我在 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。

【问题讨论】:

  • 如何在PageComponent 上使用钩子并将其发送(countsetCount 通过道具发送到EnhancedTable 组件?

标签: reactjs react-hooks


【解决方案1】:

我必须在 键入脚本 中执行此操作。面向对象方面需要开发者在继承自parent后将此回调方法作为一个字段添加到接口中,此prop的类型为Function。我觉得这很酷!

【讨论】:

    【解决方案2】:

    您可以在父组件中创建一个方法,将其传递给子组件,并在每次子组件的状态发生变化时从 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 会触发不必要的重新渲染吗?
    • @ecoe 当然可以,这取决于回调的确切作用。调用一些外部函数/调度动作应该是相对安全的,设置父级的状态——不是那么多。绝对这不是最干净的代码,所以如果可能的话,应该使用其他答案的方法。
    【解决方案3】:

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

    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。公平竞争,很好地尝试提出自己的解决方案,但有时会以一团糟而告终。坚持最佳做法和官方文档。
    【解决方案4】:

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

    示例: 假设有以下 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

    【讨论】:

    • 请提供链接中的基本详细信息,因为链接将来可能会过期。
    • 感谢您的帮助。
    【解决方案5】:

    针对这些情况的常用技术是将lift the state up 传递给需要使用状态的所有组件的第一个共同祖先(即本例中的PageComponent)并将状态和状态更改函数传递给子组件作为道具。

    示例

    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 中。然后用结果更新父级。
    • 感谢您将我从 forwardRef 的恐惧中拯救出来。它适用于我的项目。
    • 问题是如果我有 const increment (value) => { console.log(value) -> real value I've got from child c setState(value) console.log(state) - > undefined } 但在第二次 callbackCall 之后,我得到了 prev 状态值。如何解决这个问题?
    • 非常感谢。这真的帮助了我
    猜你喜欢
    • 2020-09-28
    • 1970-01-01
    • 2017-09-13
    • 1970-01-01
    • 2018-07-07
    • 2022-08-02
    • 2016-03-18
    相关资源
    最近更新 更多