【问题标题】:How to properly ask child components to do something in React Hooks如何正确要求子组件在 React Hooks 中做某事
【发布时间】:2021-01-09 22:27:26
【问题描述】:

我正在创建一个 React Hooks (17.0.1) Web 应用程序,其中有一个包含两个子组件和一个“测试”按钮的父组件。当用户选择“运行”时,我希望两个子组件做一些事情。

我的第一个想法是使用 useRef、useForwardRef 和 useImperativeHandle 来调用这些子组件中的任何一个函数。但是,通过 Google 和 SO 搜索,我了解到这通常不是 React 应该工作的方式。看完所有文章和答案,我觉得很有道理。

但是,我仍然不知道如何实现这个目标(一般来说)。那么在子组件中触发某些功能的正确方法是什么?

  • 更新子组件的属性,以便他们可以对其做出反应并运行一些代码?
  • 在父级中运行逻辑,从而将子级的信息暴露给父级?
  • ...?

【问题讨论】:

标签: reactjs react-hooks


【解决方案1】:

我只是整理了一个小演示,展示了您可以执行此操作的一种方法。它可能不是最干净的解决方案,但应该足够了。

https://codesandbox.io/s/exciting-nobel-ul3r5?file=/src/App.js

这个想法是您在父组件上保存了一组值,用于保存每个子组件是否正在执行操作。我在两者上都设置了一个计时器,可以在不同的时间完成。

只有当没有孩子正在运行他们的动作时,您才能运行测试。

我需要有关您的要求的更多信息才能提供更多建议。有很多方法可以做到这一点,并且始终取决于您的具体需求。

import React, { Fragment, useEffect, useState } from "react";

export default function App() {
  const [isTesting, setIsTesting] = useState([false, false]);

  const setChildTesting = (index) => (value) =>
    setIsTesting((isTesting) => {
      const result = [...isTesting];
      result[index] = value;
      return result;
    });

  return (
    <div>
      <button
        onClick={() => setIsTesting([true, true])}
        disabled={isTesting.some((e) => e)}
      >
        Run Test
      </button>
      <br />
      <Child1 isTesting={isTesting[0]} setIsTesting={setChildTesting(0)} />{" "}
      {isTesting[0] && "(running)"}
      <br />
      <Child2 isTesting={isTesting[1]} setIsTesting={setChildTesting(1)} />{" "}
      {isTesting[1] && "(running)"}
    </div>
  );
}

function Child1({ isTesting, setIsTesting }) {
  const [result, setResult] = useState(0);

  useEffect(() => {
    if (isTesting) {
      const interval = setInterval(() => {
        setResult((result) => result + 10);
        setIsTesting(false);
      }, 1000);
      return () => clearInterval(interval);
    }
  }, [isTesting, setResult, setIsTesting]);

  return <Fragment>Result: {result}</Fragment>;
}

function Child2({ isTesting, setIsTesting }) {
  const [result, setResult] = useState(0);

  useEffect(() => {
    if (isTesting) {
      const interval = setInterval(() => {
        setResult((result) => result + 1);
        setIsTesting(false);
      }, 2000);
      return () => clearInterval(interval);
    }
  }, [isTesting, setResult, setIsTesting]);

  return <Fragment>Result: {result}</Fragment>;
}

【讨论】:

    猜你喜欢
    • 2019-09-11
    • 2020-02-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-25
    • 2015-10-11
    • 1970-01-01
    • 2019-05-24
    相关资源
    最近更新 更多