Reputation: 341
I made a little function to add custom alerts to the state array, and the view renders them. The problem is, if i call the function twice in a row, the first alert is rendered only for a moment, and then its replaced with the second alert. When i call the method with a mouse click, the function works correctly.
I have tried to apply some waiting before pushing to the array list, but no luck with that.
const Element = () => {
const [alerts, setAlerts] = React.useState([])
const addAlert = (data) => {
setAlerts([...alerts, <CustomAlert key={alerts.length} message={data.message} color={data.color} />])
}
return (
<div>
<button onClick={() => {
// this renders only the last state update.
addAlert({message: "test", color: "error"});
addAlert({message: "2", color: "error"})
}
}>
add alert button
</button>
<div>
{alerts}
</div>
</div>
);
}
Upvotes: 1
Views: 590
Reputation: 2023
React updates the state asynchronously. This means when you are updating the state 2 times in a row, accessing the value of alerts
directly might not have the latest inserted item. You should use a function instead when calling setAlerts
:
const [alerts, setAlerts] = React.useState([]);
const addAlert = (data) => {
setAlerts((prevAlerts) => {
const newAlerts = [...prevAlerts];
newAlerts.push(
<CustomAlert
key={alerts.length}
message={data.message}
color={data.color}
/>
);
return newAlerts;
});
};
return (
<div>
<button
onClick={() => {
// this renders only the last state update.
addAlert({ message: "test", color: "error" });
addAlert({ message: "2", color: "error" });
}}
>
add alert button
</button>
</div>
);
Upvotes: 2
Reputation: 9964
alerts
in your code refers to the value of the current render in both case so your addAlert won't work. To fix this, you can use the setter version with a function:
setAlerts(currentAlerts => [...currentAlters, <CustomAlert key={alerts.length} message={data.message} color={data.color} />])
Upvotes: 1