I have code below.
// this is a function which pass to onClick props of a button
const handleDialogClick = () => {
setDialogOpen({
title: "Please Choose Language You Want",
content: (
<TextField
label="Text"
select
fullWidth
InputLabelProps={{ shrink: true }}
className="border-1 border-cadet-gray"
onChange={({ target }) => {
setPendingLanguage(target.value);
}}
>
<MenuItem value="Chinese">Chinese</MenuItem>
<MenuItem value="English">English</MenuItem>
<MenuItem value="Japanese">Japanese</MenuItem>
</TextField>
),
onCancelClick: setDialogClose,
onConfirmlClick: () => {
// below will get old reference :(
setLanguage(pendingLanguage);
setDialogClose();
}
});
};
return (
<div>
<Button variant="contained" onClick={handleDialogClick}>
click open dialog
</Button>
// some code here...
</div>
)
And feel confused about how to get new value of state, when the state be used by the props of functional component.
(I know pass a function to set function can get old value, but I’m not supposed to use old value to calculate new value.)
For compelete code, please read codesandbox
2
Answers
The problem is caused by the functions that you store in the state, for example:
When the function is stored, the current value of
pendingLanguage
is preserved in the closure. The entirehandleDialogClick
function is recreated on each render, with the current value, but since the modal is open, the functions that are saved in the atom do not.I’m not familiar enough with Jotai, but I don’t think that saving functions in the state is a good way to go. However, there’s a workaround, use a ref to store the current value of
pendingLanguage
. The ref is an object, and the stale function in the state would point to the same ref object, and you can get thecurrent
updated value.You can just assign the choosen value to a temporary variable declared at the beginning of the function.