React父组件调用子组件的方法
React组件化开发中子组件可以通过传递变量或者父组件的方法来实现和父组件的通信或者调用函数传值,但是父组件如何调用子组件的方法呢?很多介绍Hooks的文章并没有讲到useImperativeHandle,我以使用React18+TypeScript开发的项目为例,组件使用Hooks。以下是我精简过后的代码。
方法1
父组件: 父组件:
import { useState, useEffect, useRef } from "react";
import { Button } from "antd";
import AddTypeModal, { event } from "./AddTypeModal";//引入子组件和ref上的类型
const TypeList = () => {
let event = useRef({} as event);
console.log(event.current);//{opOpen:()=>{}}
return (
<> {/* 调用useRef中传来的函数 */}
<Button type="primary" onClick={() => event.current.onOpen()}>
添加
</Button>
<AddTypeModal event={event} />
</>
);
};
export default TypeList;
子组件:
import { useState, useEffect, useImperativeHandle } from "react";
import type { FC, MutableRefObject } from "react";
export type event = { onOpen: () => void };
interface PropsType {
event?: MutableRefObject<event>;
}
const AddTypeModal: FC<PropsType> = props => {
const onFinishFailed = (errorInfo: any) => {
console.log("Failed:", errorInfo);
};
useImperativeHandle(props.event, () => ({
onOpen: () => {
setIsModalVisible(true);
},
}));
return (
<>
JSX
</>
);
};
export default AddTypeModal;
方法2
其实类似方法1只是接收时有一个小小的变化
父组件:
import { useRef } from "react";
import Child from "./Child";
import "./App.css";
function App() {
let ref = useRef<any>();
return (
<div>
<button onClick={()=>ref.current.add()}>点击</button>
<div>
<Child ref={ref} />
</div>
</div>
);
}
export default App;
子组件:
import { useState, forwardRef, useImperativeHandle } from "react";
const Child = forwardRef((_, ref) => {
const [count, setCount] = useState(0);
useImperativeHandle(ref, () => ({
add: () => {
console.log(1);
setCount(c => ++c);
},
}));
return (
<>
<div>{count}</div>
</>
);
});
export default Child;
基本区别就是不在使用props进行传递和接收ref可以再子组件使用forwardRef
函数来接收ref参数,从而使用useImperativeHandle
进行修改。
其实也很简单子组件使用useImperativeHandle,父组件传递一个useRef给子组件,子组件使用useImperativeHandle来设置ref的值,这样父组件的useRef就有了子组件设置的值,就可以直接调用了。这样就达到了父组件嗲用子组件方法的目的。