Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
343 views
in Technique[技术] by (71.8m points)

reactjs - How to properly ask child components to do something in React Hooks

I'm creating a React Hooks (17.0.1) web application where there is a parent component with two child components and a 'Test' button. When 'Run' is selected by the user, then I want the two child components to do something.

My first thought was to use useRef, useForwardRef, and useImperativeHandle in order to call a function in either of those child components. However, searching through Google and SO, I understood that this is generally not the way React is supposed to work. I think it makes sense after reading all the articles and answers.

However, I still don't know how to achieve this goal (in general). So what would be the correct way to trigger some functionality in the child components?

  • Update prop of the child components so they can react to it and run some code?
  • Run the logic in the parent and therefore expose info from the children to the parent?
  • ...?
question from:https://stackoverflow.com/questions/65648250/how-to-properly-ask-child-components-to-do-something-in-react-hooks

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

I just put together a small demo of one way you can do this. It may not be the cleanest solution, but it should be enough to work from.

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

The idea is you have an array of values held on your parent component that holds whether or not each child is performing an action. I have a timer set on both to finish at different times.

You can only run the test if none of the children are currently running their action.

I'd need more information about your requirements to be able to give anymore advice. There are many ways to do this and it's always going to be dependent on your specific needs.

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>;
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...