使用 React 在父组件中公开子组件的状态和方法

Posted

技术标签:

【中文标题】使用 React 在父组件中公开子组件的状态和方法【英文标题】:Expose state and method of child Component in parent with React 【发布时间】:2022-01-12 01:18:06 【问题描述】:

我知道这样做不是一个好的模式,但你会明白我为什么要这样做。

我有一个HTable,它使用第三方库(react-table)

const HTable = <T extends object>( columns, data, tableInstance: Props<T>) 
   const instance: TableInstance<T> = useTable<T> (
   // Parameters
   )
   React.useImperativeHandle(tableInstance, () => instance);

现在,我想从父级控制列的可见性。我做到了:

const Parent = () => 
      const [tableInstance, setTableInstance] = React.useState<TableInstance<SaleItem>>();

      <Table data=data columns=columns tableInstance=(instance) => setTableInstance(instance)

       return tableInstance.columns.map((column) => 
           <Toggle active=column.isVisible onClick=() =>column.toggleHiden()
       

该列隐藏得很好,但状态没有更新,切换也没有,我不明白为什么。你能帮我理解吗?

编辑:

添加沙盒。

https://codesandbox.io/s/react-table-imperative-ref-forked-dilx3?file=/src/App.js

请注意,我不能使用 React.forwardRef,因为我使用 typescript,如果我使用 forwardRef,React.forwardRef 不允许这样的泛型类型

interface TableProps<T extends object> 
    data: T[],
    columns: Column<T>[],
    tableInstance?:  React.RefObject<TableInstance<T>>,

【问题讨论】:

看起来您发布的代码 sn-ps 有点混乱。你能纠正这些吗?另外,当您单击 Toggle 时,您能否确认您的 Parent 中的 tableInstance 已重新设置? - 如果您能提供一个我们可以测试的示例,也会很有帮助! 我添加了一个沙箱。注意第二个复选框没有更新。 【参考方案1】:

您的问题是 react-tables useTable() 钩子总是返回与 instance 包装器相同的对象(引用永远不会改变)。因此,您的父母正在将 tableInstance 重新设置为同一个对象 - 这不会触发更新。实际上,大多数包含的值也被记住了。要获得它的响应式获取 headerGroups 属性。

const 
  headerGroups,
  ...otherProperties,
 = instance;

React.useImperativeHandle(
  tableInstance,
  () => ( ...properties ), // select properties individually
  [headerGroups, ...properties],
);

【讨论】:

你能提供一个沙箱吗?当我这样做时,我有一个无限的渲染。如果我使用 createRef 而不是 useState,问题仍然存在。 @PaulSerre 您的沙箱有一个内联函数作为道具传递给第 109 行的Table,它会触发重新渲染。检查here 谢谢你,真的!最后一个问题,可以用 ref 来做吗?它是一个可重用的组件,所以如果它与 ref 一起使用会更不稳定 当然,你可以只传递一个 ref 而不是你的 setter 函数。这些属性将在ref.current.columns... 公开。但是这个 ref 不会是反应性的/它不会重新渲染。您将不得不找到另一种方法来使其具有反应性。除此之外,为了使其更易于理解/可重用,也许您可​​以找到一种方法将表格移动到它自己的自定义钩子中,或者让它接受子切换按钮! 谢谢!最后一个我不能点它,因为我必须制作一个外部按钮,这意味着我必须能够将它放在桌子外面:/

以上是关于使用 React 在父组件中公开子组件的状态和方法的主要内容,如果未能解决你的问题,请参考以下文章

React 子组件在父组件中更新状态后如何将其重置回原始状态

在父组件的状态更改中重新呈现子组件

react 子组件调用父组件方法

React 父/子状态更改设计问题

React组件间的通信

React组件间通信