please help. When function "handleAddToken" is triggered, useEffect uses the previous old state of tokenData, instead of the new one.
It results in tokens being added in a desynchronized way (zero tokens after I add 1st token, then 1st token and I added 2nd token, etc)
Here’re all of the states:
// this one opens modal window where you enter values which go inside token data
const [open, setOpen] = React.useState(false);
// this one is to set data inside token {}
const [tokenData, setTokenData] = React.useState({});
// this one is a token that is added inside the array of tokens, which then is mapped as elements
const [token, setNewToken] = React.useState<JSX.Element>();
The useEffect:
React.useEffect(() => {
// tokenId is undefined at the beginning, but is defined after handleAddToken is called (see below)
if ((tokenData as TokenData).tokenId) {
// assembleToken returns a JSX Element that is assembled with tokenData
setNewToken(assembleToken(tokenData as TokenData));
// adds token inside array of other tokens (addToken is a useState state setter from another module)
props.addToken([...props.tokenArray, token]);
// to reset tokendata
setTokenData({
tokenTrueName: "",
tokenAlias: null,
tokenId: "",
tokenType: "",
tokenLabelColor: "",
tokenStatusColor: "",
linkedTo: null,
tokenInitiative: 0,
tokenHP: "",
tokenDefense: "",
tokenSpeed: "",
});
}
}, [tokenData, token]);
This function is called, when I click the "Add token" button.
function handleAddToken() {
// adds additional data (other data, like tokenAlias ot trueName is being added onChange, that is triggered when you type in fields within a modal window, I didn't include this function here)
setTokenData({
...tokenData,
tokenId: uuidv4(),
tokenType: currentTokenType,
tokenLabelColor: randomColor(),
tokenStatusColor: "gray",
linkedTo: null,
});
// closes MUI modal window
setOpen(false);
}
Whatever I tried didn’t work, unfortunately
>Solution :
when you use a setState function and you try to get the new state in the same scope it won’t work because the state is async, in this case you need to separate in two useEffects
React.useEffect(() => {
// tokenId is undefined at the beginning, but is defined after handleAddToken is called (see below)
if ((tokenData as TokenData).tokenId) {
// assembleToken returns a JSX Element that is assembled with tokenData
setNewToken(assembleToken(tokenData as TokenData));
// to reset tokendata
setTokenData({
tokenTrueName: "",
tokenAlias: null,
tokenId: "",
tokenType: "",
tokenLabelColor: "",
tokenStatusColor: "",
linkedTo: null,
tokenInitiative: 0,
tokenHP: "",
tokenDefense: "",
tokenSpeed: "",
});
}
}, [tokenData]);
useEffect(() => {
props.addToken([...props.tokenArray, token]);
}, [token])