如何获取 React 组件的状态以实现全局保存按钮
How to obtain state of a React Component to implement a global Save-Button
我们开发了一个可重用的 table-like 组件,具有 Reacts 功能组件样式。
table 使用 React.useReducer 保存、管理和验证它的状态。
在每一行中都有几个输入字段、复选框和操作按钮来修改 row/table-state.
现在 GUI 中的其他地方有一个保存按钮(不是 table 的子项)。
如何从 table 检索状态,以便将其(与其他一些数据一起)发送到 REST 端点以实现持久性?
我们实际的解决方案是一个回调函数,它将被设置为 table 上的一个属性。
每次渲染后从 table-component 内部调用此函数以发布当前状态的副本。
现在此回调函数的所有者获取并保存此数据,以便它在保存按钮的范围内可用。
function ComponentWrapper(props)
{
const dataRef = React.useRef(props.initialData);
function onDataUpdate(newData) {
dataRef.current = newDate;
}
function saveData() {
// send dataRef.current to REST-Endpoint
}
return (
<div>
<MyTable onDataUpdate={onDataUpdate}></MyTable>
...
<button onClick={(e) => sendData()} name="save">Save</button>
</div>
);
}
function MyTable(props)
{
const [state, dispatch] = useReducer(..., props.initialData)
// ... some code to dispatch state changing actions
useEffect(() => {
const copyOfState = { ...state }
props.onDataUpdate(copyOfState);
});
return (
// table markup goes here ...
);
}
这确实有效,但我们相信对于此类用例可能有更好的方法。
我们不想将状态从 table 提升到 ComponentWrapper,因为 table 应该是可重用的,并且保存按钮可能位于 GUI 中完全不同的位置(例如,在工具栏或一个菜单)。
对此有什么想法吗?提前致谢。
如果您的 table 当前正在管理自己的状态,那么您需要提升该状态,或将其移至某个全局存储区。正如您所说,将保存功能作为回调从树上的某个组件传递,该组件也是保存按钮的父级。
但更优雅和用户友好的解决方案是使用一些 context, or use redux.
使用上下文,您的保存函数可以将该值传递给上下文对象,该对象可以在树的其他位置检索。有很多关于如何做到这一点的好文章 - here is one, and here is another.
Redux 与此类似,并且已成为您最喜欢做的事情。您可以使用 redux reducer 将 table 数据保存到全局存储,然后您的 'save' 按钮可以调用从存储中检索此数据并将其发送到您的 REST 端点,而不管它在树到 table。在需要跨多个组件协调状态的大型应用程序中,它绝对是首选。
我们开发了一个可重用的 table-like 组件,具有 Reacts 功能组件样式。 table 使用 React.useReducer 保存、管理和验证它的状态。 在每一行中都有几个输入字段、复选框和操作按钮来修改 row/table-state.
现在 GUI 中的其他地方有一个保存按钮(不是 table 的子项)。 如何从 table 检索状态,以便将其(与其他一些数据一起)发送到 REST 端点以实现持久性?
我们实际的解决方案是一个回调函数,它将被设置为 table 上的一个属性。 每次渲染后从 table-component 内部调用此函数以发布当前状态的副本。 现在此回调函数的所有者获取并保存此数据,以便它在保存按钮的范围内可用。
function ComponentWrapper(props)
{
const dataRef = React.useRef(props.initialData);
function onDataUpdate(newData) {
dataRef.current = newDate;
}
function saveData() {
// send dataRef.current to REST-Endpoint
}
return (
<div>
<MyTable onDataUpdate={onDataUpdate}></MyTable>
...
<button onClick={(e) => sendData()} name="save">Save</button>
</div>
);
}
function MyTable(props)
{
const [state, dispatch] = useReducer(..., props.initialData)
// ... some code to dispatch state changing actions
useEffect(() => {
const copyOfState = { ...state }
props.onDataUpdate(copyOfState);
});
return (
// table markup goes here ...
);
}
这确实有效,但我们相信对于此类用例可能有更好的方法。 我们不想将状态从 table 提升到 ComponentWrapper,因为 table 应该是可重用的,并且保存按钮可能位于 GUI 中完全不同的位置(例如,在工具栏或一个菜单)。
对此有什么想法吗?提前致谢。
如果您的 table 当前正在管理自己的状态,那么您需要提升该状态,或将其移至某个全局存储区。正如您所说,将保存功能作为回调从树上的某个组件传递,该组件也是保存按钮的父级。
但更优雅和用户友好的解决方案是使用一些 context, or use redux.
使用上下文,您的保存函数可以将该值传递给上下文对象,该对象可以在树的其他位置检索。有很多关于如何做到这一点的好文章 - here is one, and here is another.
Redux 与此类似,并且已成为您最喜欢做的事情。您可以使用 redux reducer 将 table 数据保存到全局存储,然后您的 'save' 按钮可以调用从存储中检索此数据并将其发送到您的 REST 端点,而不管它在树到 table。在需要跨多个组件协调状态的大型应用程序中,它绝对是首选。