Child 使用 useState() 设置道具时不会重新渲染
Child not rerendered when prop set with useState()
我有一种情况,我有 parent (App
) 和 child (MUIDatatable
) 组件。 child 是一个数据表,它接受 columns
属性描述列结构以及为其中之一定义自定义渲染函数。在这个自定义渲染函数中,我创建了一个按钮实例,其 disabled
状态应取决于 parent 的状态,取决于通过 useState()
挂钩设置的 buttonsDisabled
值。到目前为止它工作正常,但是当我还使用 useState()
更改 columns
道具时,更改 buttonsDisabled
值时不再触发重新渲染。代码如下所示:
const App = () => {
const [buttonsDisabled, setButtonsDisabled] = useState(false);
const tableData = {
columns: [
{ name: "name", label: "Name", options: {} },
{
name: "action",
label: "Action",
options: {
customBodyRender: v => (
<button disabled={buttonsDisabled}>button</button>
)
}
}
],
data: [["A", null], ["B", null], ["C", null], ["D", null]]
};
const btnOnClick = () => {
setButtonsDisabled(true);
};
/***** discussed part of code *****/
const [columns] = useState(tableData.columns); // if we use this, buttons are not disabled
//const columns = tableData.columns; // if we use this, buttons are properly disabled
/**********************************/
return (
<div>
<button onClick={btnOnClick}>DISABLE BUTTONS</button>
<MUIDataTable title="title" data={tableData.data} columns={columns} />
</div>
);
};
它也可以在 codesandbox 上找到:
https://codesandbox.io/s/muidatatables-custom-toolbar-cy4vg
我准备的代码是我原来的代码的精简版,所以它可能没有多大意义,但它把代码限制在最低限度,只是为了能够重现问题。
我不明白的是为什么使用useState
修改columns
值会阻止指定的customBodyRender
函数在buttonsDisabled
值更改时被触发,而通过简单的赋值设置它就可以了。在这两种情况下,它毕竟仍然是对同一个数组的引用。我相信这是我遗漏的一些简单概念,但如果有人帮助指出那是什么,我将不胜感激。
当您创建初始 columns
状态时,您的 customBodyRender
函数可以访问外部函数的 buttonsDisabled
变量(参见:closure),该变量默认为false
。一旦初始化,你的 columns
变量就存储在你的状态中,customBodyRender
内部的 buttonsDisabled
变量将继续引用外部函数的原始值。
您是否可以将 buttonsDisabled
传递给 MUIDataTable
table 组件,并可能将其作为参数传递给 customBodyRender
函数?
customBodyRender: (v, disabled) => (
<button disabled={disabled}>button</button>
)
我有一种情况,我有 parent (App
) 和 child (MUIDatatable
) 组件。 child 是一个数据表,它接受 columns
属性描述列结构以及为其中之一定义自定义渲染函数。在这个自定义渲染函数中,我创建了一个按钮实例,其 disabled
状态应取决于 parent 的状态,取决于通过 useState()
挂钩设置的 buttonsDisabled
值。到目前为止它工作正常,但是当我还使用 useState()
更改 columns
道具时,更改 buttonsDisabled
值时不再触发重新渲染。代码如下所示:
const App = () => {
const [buttonsDisabled, setButtonsDisabled] = useState(false);
const tableData = {
columns: [
{ name: "name", label: "Name", options: {} },
{
name: "action",
label: "Action",
options: {
customBodyRender: v => (
<button disabled={buttonsDisabled}>button</button>
)
}
}
],
data: [["A", null], ["B", null], ["C", null], ["D", null]]
};
const btnOnClick = () => {
setButtonsDisabled(true);
};
/***** discussed part of code *****/
const [columns] = useState(tableData.columns); // if we use this, buttons are not disabled
//const columns = tableData.columns; // if we use this, buttons are properly disabled
/**********************************/
return (
<div>
<button onClick={btnOnClick}>DISABLE BUTTONS</button>
<MUIDataTable title="title" data={tableData.data} columns={columns} />
</div>
);
};
它也可以在 codesandbox 上找到: https://codesandbox.io/s/muidatatables-custom-toolbar-cy4vg
我准备的代码是我原来的代码的精简版,所以它可能没有多大意义,但它把代码限制在最低限度,只是为了能够重现问题。
我不明白的是为什么使用useState
修改columns
值会阻止指定的customBodyRender
函数在buttonsDisabled
值更改时被触发,而通过简单的赋值设置它就可以了。在这两种情况下,它毕竟仍然是对同一个数组的引用。我相信这是我遗漏的一些简单概念,但如果有人帮助指出那是什么,我将不胜感激。
当您创建初始 columns
状态时,您的 customBodyRender
函数可以访问外部函数的 buttonsDisabled
变量(参见:closure),该变量默认为false
。一旦初始化,你的 columns
变量就存储在你的状态中,customBodyRender
内部的 buttonsDisabled
变量将继续引用外部函数的原始值。
您是否可以将 buttonsDisabled
传递给 MUIDataTable
table 组件,并可能将其作为参数传递给 customBodyRender
函数?
customBodyRender: (v, disabled) => (
<button disabled={disabled}>button</button>
)