react实现父组件直接执行子组件的方法(useRef)

您所在的位置:网站首页 react父组件怎么调用子组件的方法 react实现父组件直接执行子组件的方法(useRef)

react实现父组件直接执行子组件的方法(useRef)

2024-07-15 21:07| 来源: 网络整理| 查看: 265

今天遇到这样一个需求:

一个很简单的左右布局。要实现点击左侧数据更新右侧表格。这个表格因为在多处用到,所以被单独封装。表格勾选和全选的逻辑写在了表格这个组件内部。而这也导致了一个问题:每次点击左侧的数据,右侧的表格并没有重置状态。那如何解决这个问题?

表格的全选和勾选与全选的状态关联是根据selectRowKeys来控制的。如果selectRowKeys=[],那表格每行的勾选状态将被清空。所以关键就是要在每次点击左侧树形菜单的时候进selectRowKeys的操作。

第一种方法:既然表格的状态被单独封装到了表格的组件里。那我再点击父组件左侧的树形菜单时,直接操作表格组件本身,然后通过组件本身的方法去做操作不就可以了吗?沿着这个思路。

我们引出来reactHooks里几个钩子:

useImperativeHandle

useRef

forwardRef

具体使用如下:

(1)父组件使用 useRef 创建一个 ref 传入 子组件

const childrenRef = useRef(null);

return

(2)子组件使用 useImperativeHandle 暴露 ref 自定义的实例值给父组件。这个需要用 forwardRef 包裹

function children(props, ref) { useImperativeHandle(ref, () => ({ hello: () => console.log('hello world!') })) return children } export default forwardRef(children);

最后在父组件中调用

const childrenRef = useRef(null); const something = () => childrenRef.current.hello();

还是回到我们的表格这个案例。我们看看封装的table这个组件

import { useState, useEffect, useImperativeHandle, forwardRef } from "react" import { Table, Row, Col, Checkbox } from "antd" import "./index.less" function QuotaTable(props, ref) { console.log("表格props:", props) let { columns, dataSource, total, resetTable, queryQuotaByPage, renderTitleRtConts = } = props // renderTitleRtConts 头部右侧操作内容 const [selectedRowKeys, setSelectedRowKeys] = useState([]) const [isCheckeAll, setIsCheckeAll] = useState(false) const reset = () => { setSelectedRowKeys([]) setIsCheckeAll(false) } const selectAll = (e) => { let keys = [] if (e.target.checked) { keys = dataSource.map(i => i.key) } else { keys = [] } console.log("keys:", keys) setSelectedRowKeys(keys) setIsCheckeAll(e.target.checked) props.getSelectedTableIds(keys) } const changePage = (cur) => { console.log("cur:", cur) queryQuotaByPage(cur) } const rowSelection = { onChange: (selectedRowKeys, selectedRows) => { if (selectedRowKeys.length === dataSource.length) { setSelectedRowKeys(selectedRowKeys) setIsCheckeAll(true) } else { setSelectedRowKeys(selectedRowKeys) setIsCheckeAll(false) } props.getSelectedTableIds(selectedRowKeys) }, selectedRowKeys, getCheckboxProps: (record) => ({ disabled: record.name === 'Disabled User', name: record.name, }), }; useImperativeHandle(ref, () => ({ selectAll, reset, rowSelection })) //分液器设置 const paginationProps = { showSizeChanger: true,//设置每页显示数据条数 showQuickJumper: false, showTotal: () => `共${total}条`, pageSize: 20, total, //数据的总的条数 onChange: (current) => changePage(current), //点击当前页码 } return ( selectAll(e)} checked={isCheckeAll}>全选 已选{selectedRowKeys.length}个对象,共1200个对象 {renderTitleRtConts} } resetTable={resetTable} hideSelectAll={true} rowSelection={rowSelection} columns={columns} dataSource={dataSource} pagination={paginationProps} > ) } export default forwardRef(QuotaTable)

注意:我们把要暴露出去的方法通过useImperativeHandle进行包装,通过把QuotaTable这个组件通过forwardRef进行包裹。这里我们其实只需要暴露reset这个方法即可。

最后我们在父组件中调用:

const selectTree = (selectedKeys, { node }) => { let item = deepCopy(node) let params = {} if (node.code) { //点击其他层级 params = { ...quotaParams, categoryId: node.id, shopCode: activeKey, setMealCode: node.code } } else { params = { ...quotaParams, setMealCode: node.id, shopCode: activeKey } } console.log("params", params) setCurTreeItem(item) setQuotaParams(params) queryQuota(params) //重置表格勾选状态 tableRef.current.reset() } return ( { treeData.length == 0 ? : } 复制 0 ? false : true} onClick={remove} > 移除 }> )

tableRef.current获取到子组件的实例以后直接调用reset方法就可以解决这个问题



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3