I have a situation where I have parent (App
) and child (MUIDatatable
) component. The child is a datatable which accepts columns
prop describing columns structure along with defining custom render function for one of them. In this custom render function I create a button instance for which disabled
state should depend on parent's state, on buttonsDisabled
value which is set via useState()
hook. Up to this point it works fine, but when I also change the columns
prop using useState()
, the rerender does not trigger anymore when changing buttonsDisabled
value. The code looks like this:
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>
);
};
It's also available at codesandbox: https://codesandbox.io/s/muidatatables-custom-toolbar-cy4vg
The code that I prepared is a stripped version of my original one so it might not make a lot of sense, but it limits the code to the bare minimum, just to be able to reproduce the problem.
What I can't understand is why does using useState
to modify columns
value would prevent specified customBodyRender
function from being triggered when buttonsDisabled
value is changed, whereas setting it via simple assignment works just fine. In both cases it's still the reference to the same array after all. I believe this is some simple concept that I'm missing, but I would appreciate some help in pointing out what's that.
When you create your initial columns
state, your customBodyRender
function has access to the outer function's buttonsDisabled
variable (see: closure), which is defaulted to false
. Once initialized, your columns
variable is stored in your state, and the buttonsDisabled
variable inside customBodyRender
will continue to reference the original value from the outer function.
Would it be possible for you to instead pass buttonsDisabled
into your MUIDataTable
table component, and perhaps pass it as an argument to the customBodyRender
function?
customBodyRender: (v, disabled) => (
<button disabled={disabled}>button</button>
)