I've put a simple boolean state on a custom header, the plan is the make this state control a dropdown menu. I've used a simple onClick on this custom header that set the states to it's opposite value and after that logs the state. But the state stays the same and doesn't change on each click.
This happens when I set the columns with an initial setState because I need my table to be fully server side based. When setting the columns with a normal let it works but that's not the particular need.
header is highlighted, click on it and you will see the state log in the console.
export default function PositioningActionsColumn() {
const [stateData, setStateData] = useState([]);
const [stateColumns, setStateColumns] = useState([]);
const [isOpen, setIsOpen] = useState(false);
// setting the columns and data - will be from a fetch later
useEffect(() => {
setStateColumns([
{
title: nameHeader,
field: "name"
},
{
title: "Surname",
field: "surname",
initialEditValue: "initial edit value"
},
{ title: "Birth Year", field: "birthYear", type: "numeric" },
{
title: "Birth Place",
field: "birthCity",
lookup: { 34: "İstanbul", 63: "Şanlıurfa" }
}
]);
setStateData([
{ name: "Mehmet", surname: "Baran", birthYear: 1987, birthCity: 63 },
{ name: "Zerya Betül", surname: "Baran", birthYear: 2017, birthCity: 34 }
]);
}, []);
const orderFunc = (orderedColumnId, orderDirection) => {
console.log(
"orderedColumnId:",
orderedColumnId,
"orderDirection:",
orderDirection
);
};
const searchFunc = e => {
console.log(e);
};
const handleClick = () => {
setIsOpen(!isOpen);
console.log(isOpen);
};
const nameHeader = (
<div style={{ background: "lightblue" }} onClick={handleClick}>
Click on this custom Name Header
</div>
);
return (
<MaterialTable
title="Editable Preview"
icons={tableIcons}
columns={stateColumns}
data={stateData}
onOrderChange={(orderedColumnId, orderDirection) => {
orderFunc(orderedColumnId, orderDirection);
}}
onSearchChange={e => searchFunc(e)}
options={{ draggable: false, selection: true, actionsColumnIndex: -1 }}
actions={[
{
tooltip: "Remove All Selected Users",
icon: "delete",
onClick: (evt, data) => {
console.log({ data });
alert("You want to delete " + data.length + " rows");
}
},
{
isFreeAction: true,
tooltip: "FreeAction",
icon: () => <div>Free</div>,
onClick: (evt, data) => {
console.log({ data });
}
}
]}
editable={{
onRowAdd: newData =>
new Promise((resolve, reject) => {
setTimeout(() => {
{
console.log({ newData });
const data = stateData;
data.push(newData);
setStateData(data, () => resolve());
}
resolve();
}, 1000);
}),
onRowUpdate: (newData, oldData) =>
new Promise((resolve, reject) => {
setTimeout(() => {
{
console.log({ newData }, { oldData });
const data = stateData;
const index = data.indexOf(oldData);
data[index] = newData;
setStateData(data, () => resolve());
}
resolve();
}, 1000);
}),
onRowDelete: oldData =>
new Promise((resolve, reject) => {
setTimeout(() => {
{
console.log({ oldData });
let data = stateData;
const index = data.indexOf(oldData);
data.splice(index, 1);
setStateData(data, () => resolve());
}
resolve();
}, 1000);
})
}}
/>
);
}
https://codesandbox.io/s/material-table-testing-actions-position-and-output-2-sj1tt
console.logdirectly after callingsetState(). - trixnisOpenas a dependency to your callback. It will never be reconstructed and always dosetIsOpen(!false)becausefalsewas the value when it was first created and b) you are constructing a component with the handler that you store in state in auseEffectthat also only gets called on mount. So your component never changes, including the handler attached to it. Also you should not save elements in state. State should consist of plain data. - trixn