将 parent 状态替换为 child 状态。 parent 中的按钮

Replace parent state with state of child. Button in parent

编辑: 请参阅 O.o 的评论以了解答案的解释以及您使用 类 时的变体。

我遇到了一些问题,但找不到解决方案。

我的网络应用程序中有 4 个组件:

Parent
   child_1
   child_2
   child_3

我在 Parent 上有一个按钮,在 children 上有不同的表单(带有输入、复选框和单选按钮)。

每个 child 都有自己的按钮,可以执行多个功能、一些计算并更新相应的状态。 (没有状态通过 parent 和 child)。

我需要把children的三个按钮换成parent按钮。 有没有办法可以通过 parent 按钮执行三个 children 的功能并检索结果? (结果是 state:value 每 child。)

function Child1(props) {
   const [value, setValue] = useState("");
   useEffect(() => {
      calculate();
   }, [props.flag]);
   calculate() {
       //blah blah
   }
   onChange(e) {
      setValue(e.target.value);
      props.onChange(e.target.value); // update the state in the parent component
   }
   return (
      <input value={value} onChange={(e) => onChange(e)} />
   );
}

function Parent(props) {
  const [flag, setFlag] = useState(false);
  const [child1Value, setChild1Value] = useState("");
  return (
    <div>
       <Child1 flag={flag} onChange={(value) => setChild1Value(value)}/>
       <button onClick={() => setFlag(!flag)} />
    </div>
  );
}

我没有对此进行测试,但希望对您有所帮助。让我知道是否有问题。

尝试以下操作:

  • 使用 useRef 为 child 表单组件创建引用。
  • 对于功能组件,为了让parent访问child的方法,你需要使用forwardRef
  • 使用 ref,在单击 parent 提交按钮时调用 child 组件函数(使用 ref.current.methodName

查看示例代码。我在本地测试过,没问题。

Parent

import React, { Fragment, useState, useRef } from "react";
import ChildForm1 from "./ChildForm1";

const Parent = props => {
  const [form1Data, setFormData] = useState({});//use your own data structure..
  const child1Ref = useRef();
  // const child2Ref = useRef(); // for 2nd Child Form...

  const submitHandler = e => {
    e.preventDefault();
    // execute childForm1's function
    child1Ref.current.someCalculations();
    // execute childForm2's function

    //    finally do whatever you want with formData
    console.log("form submitted");
  };

  const notifyCalcResult = (calcResult) => {
      // update state based on calcResult
      console.log('calcResult', calcResult);
  };

  const handleChildFormChange = data => {
    setFormData(prev => ({ ...prev, ...data }));
  };

  return (
    <Fragment>
      <h1 className="large text-primary">Parent Child demo</h1>
      <div>
        <ChildForm1
            notifyCalcResult={notifyCalcResult}
            ref={child1Ref}
            handleChange={handleChildFormChange} />
          {/*{do the same for ChildForm2 and so on...}*/}
        <button onClick={submitHandler}>Final Submit</button>
      </div>
    </Fragment>
  );
};

export default Parent;

ChildFormComponent

import React, { useState, useEffect, forwardRef, useImperativeHandle } from "react";

const ChildForm1 = ({ handleChange, notifyCalcResult }, ref) => {
  const [name, setName] = useState("");
  const [calcResult, setCalcResult] = useState([]);

  const someCalculations = () => {
    let result = ["lot_of_data"];
    //  major calculations goes here..
    //  result = doMajorCalc();
    setCalcResult(result);
  };
  useImperativeHandle(ref, () => ({ someCalculations }));

  useEffect(() => {
    //  notifiy parent
    notifyCalcResult(calcResult);
  }, [calcResult]);

  return (
    <form className="form">
      <div className="form-group">
        <input
            value={name}// //TODO: handle this...
          onChange={() => handleChange(name)}//TODO: notify the value back to parent 
          type="text"
          placeholder="Enter Name"
        />
      </div>
    </form>
  );
};

export default forwardRef(ChildForm1);

同样作为最佳实践,考虑尽可能维护 parent 组件中的状态和功能,并将所需的 values/methods 作为 props 传递给 child。