Calling Child Component Function From Parent Component Give Error : Cannot read properties of undefined

Calling Child Component Function From Parent Component Give Error : Cannot read properties of undefined

我有 Child 个这样的组件。

Parent => 子Parent => Child

我在 Child 组件中有一个函数,我需要在 Parent.To 中调用这个函数,我使用 React Hooks。 (我参考了This文章来做到这一点。因为我是reatjs的新学生。)

这是我的代码。

import React, {forwardRef, useRef, useImperativeHandle} from 'react';
import {Button} from '@material-ui/core';

function Parent(props) {
    const childRef = useRef();
    const addDate = () =>{
        childRef && childRef.current.submitHandler();
    };
    return (
        <div>
            {/* eslint-disable-next-line react/jsx-no-undef */}
            <Button
                onClick={addDate}>
                SAVE
            </Button>
            <SubParent ref={childRef}/>
        </div>
    );
}


function SubParent(props) {
    return (
        <div>
            <Child ref={props.ref}/>
        </div>
    );
}


const Child = forwardRef((props, ref) => {
    const submitHandler = () => {};
    useImperativeHandle(
        ref,
        () => ({
            submitHandler,
        }),
    );

    return (
        <div>Child Component</div>
    );
});

但是当我按下 Parent 组件中的按钮时出现此错误。

Error Image Link

TypeError: 无法读取未定义的属性(读取 'submitHandler')

我找不到我的错误。如果有人可以帮助我,我真的很感激。 非常感谢。❤️

我认为您的方向是正确的。但是,也只需要转发来自 SubParent 组件的 ref,否则它将附加到 SubParent 组件而不是 Child 组件

这是代码框:https://codesandbox.io/s/vigorous-hooks-o5n5s?file=/src/App.js:215-780

function Parent(props) {
  const childRef = useRef();
  const addDate = () => {
    childRef && childRef.current.submitHandler();
  };
  return (
    <div>
      <Button onClick={addDate}>SAVE</Button>
      <SubParent ref={childRef} />
    </div>
  );
}

const SubParent = React.forwardRef((props, ref) => ( // check this implementation
  <div>
    <Child ref={ref} />
  </div>
));

const Child = forwardRef((props, ref) => {
  const submitHandler = () => {
    console.log("Called");
  };

  useImperativeHandle(ref, () => ({
    submitHandler
  }));

  return <div>Child Component</div>;
});

您不能从中间 SubParent 组件中的默认 props 对象转发 ref,因为 ref 不是通过这种方式传递的。

来自 Forwarding refs to DOM components

Regular function or class components don’t receive the ref argument, and ref is not available in props either.

您需要对父组件和最终子组件之间的每个组件应用 forwardRef()

const { forwardRef, useRef, useImperativeHandle } = React;

function Parent(props) {
  const childRef = useRef();
  const addDate = () => {
    childRef && childRef.current.submitHandler();
  };

  return (
    <div>
      <button onClick={addDate}>SAVE</button>
      <SubParent ref={childRef} />
    </div>
  );
}

const SubParent = forwardRef((props, ref) => {
  return (
    <div>
      <Child ref={ref} />
    </div>
  );
});

const Child = forwardRef((props, ref) => {
  const submitHandler = () => {
    console.log('In submit handler');
  };
  useImperativeHandle(ref, () => ({ submitHandler }));

  return <div>Child Component</div>;
});

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

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

您几乎完成了所有操作,但只有一点,您需要将 forwardRef 而不是 ref 传递到 SubParent:

import React, { forwardRef, useRef, useImperativeHandle } from "react";
import { Button } from "@material-ui/core";

function Parent(props) {
  const childRef = useRef();
  const addDate = () => {
    console.log("from parent component");
    childRef?.current?.submitHandler();
  };
  return (
    <div>
      <Button onClick={addDate}>SAVE</Button>
      <SubParent forwardRef={childRef} />
    </div>
  );
}

function SubParent(props) {
  return (
    <div>
      <Child ref={props.forwardRef} />
    </div>
  );
}

const Child = forwardRef((props, ref) => {
  const submitHandler = () => {
    console.log("from child component");
  };
  useImperativeHandle(ref, () => ({
    submitHandler: submitHandler
  }));

  return <div>Child Component</div>;
});

export default Parent;

试穿codesandbox