React hooks子组件暴露方法示例
说明
通常情况下,React 子组件使用父组件的方法或值通过props传递,反过来,父组件如果需要子组件的方法就需要子组件将自己的方法暴露出去。以下是一个实例:
User.tsx
import React, { FC, useEffect, useState, useRef } from 'react'; import { Button, Table } from 'antd'; import UserEdit, { UserEditRef } from './UserEdit'; import { EditFilled } from '@ant-design/icons'; interface User { desc?: string; name?: string; } const User: FC = () => { const userEditRef = useRef<UserEditRef>(null); const columns: any = [ { title: '名称', dataIndex: 'name', key: 'name', }, { title: '描述', dataIndex: 'desc', key: 'desc', }, { title: '操作', render: (_: string, record: User) => { return ( <EditFilled onClick={(e) => { userEditRef.current?.open(record); }} /> ); }, }, ]; const [datasource, setDatasource] = useState<User[]>([ { desc: 'I am Tom', name: 'Tom', }, { desc: 'I am Marry', name: 'Marry', }, ]); const updateData = (data?: User) => { const datas = [data, ...datasource]; setDatasource(datas); }; return ( <div> <Button onClick={() => { userEditRef.current.open(); }} > 新建 </Button> <Table columns={columns} dataSource={datasource} /> <UserEdit ref={userEditRef} onSave={updateData} /> </div> ); }; export default User;
UserEdit.tsx
import { useState, useImperativeHandle, forwardRef } from 'react'; import { Form, Input, Drawer, Button } from 'antd'; interface User { userId?: number; desc?: string; name?: string; } interface PropType { onSave: Function; } export interface UserEditRef { open: (currentUser?: User) => void; } const UserEdit = forwardRef<UserEditRef, PropType>((props, ref) => { //props const { onSave } = props; // state const [userEditOpen, setUserEditOpen] = useState(false); const [currentFormData, setCurrentFormData] = useState<User>(); // 暴露给父组件的属性,open是打开抽屉的方法 useImperativeHandle(ref, () => ({ open: (currentUser?: User) => { setUserEditOpen(true); setCurrentFormData(currentUser); }, })); const onCancel = () => { setUserEditOpen(false); }; const onFinish = (values: any) => { onSave(values); setUserEditOpen(false); }; return ( <Drawer title={ currentFormData ? '用户 | ' + currentFormData?.name : '用户 | 新建' } width="auto" open={userEditOpen} footer={null} onClose={onCancel} destroyOnClose > <Form initialValues={currentFormData} onFinish={onFinish}> <Form.Item label="组名" name="name" rules={[{ required: true, message: '请输入用户名!' }]} > <Input /> </Form.Item> <Form.Item label="描述" name="desc"> <Input.TextArea /> </Form.Item> <Form.Item> <Button type="primary" htmlType="submit"> 提交 </Button> <Button htmlType="button" onClick={onCancel} style={{ marginLeft: 8 }} > 取消 </Button> </Form.Item> </Form> </Drawer> ); }); export default UserEdit;