This is a simplified version of my code, where I am having a problem.
const Certificates = () => {
const [currentList, setCurrentList] = useState(false);
const [sort, setSort] = useState('posted');
useEffect(() => {
if (gameDetails) {
setCurrentList({})
}
}, [gameDetails])
useEffect(() => {
if (sort === 'alphabetical') {
setCurrentList([])
}
}, [sort])
return (
<>
{
currentList && sort === 'posted' && Object.keys(currentList)
}
{
currentList && sort === 'alphabetical' && currentList.map
}
</>
)
}
I have a state variable which changes from Object
to Array
depending on the active sort.
I have a conditional rendering where if the sort is 'posted' it must do the rendering considering the state variable is a Object
.
if the sort is 'alphabetical', it must do the rendering considering the state variable is a Array
.
The problem is when the state variable changes from Object
to Array
, I am getting a currentList.map is not a function
error.
When rendering react is considering currentList as a Object
even though its changed to a Array
.
The proof for the above statement is: I tried doing this:
<div>
{
currentList && console.log(currentList)
}
</div>
When the state variable changes to an Array
this is the log I am getting:
-> {20/09/2022: Array(1), 18/01/2022: Array(1), 30/06/2021: Array(1), 24/06/2021: Array(5)}
-> [{…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}]
When the state changes React first tries to render the previous state, that is where the error is occurring.
How can I solve this, any help will be appriciated.
CodePudding user response:
I'm not sure exactly what you're trying to achieve here, but I believe your problem is caused by stale closure occurring when use hooks, you can read up on it here: https://dmitripavlutin.com/react-hooks-stale-closures/.
In React state is only updated after the current execution context is finished - that's why it takes two re-renders to get the desired state.
I also had this issue some time ago, this question might help: React function takes two button clicks to run.
CodePudding user response:
Because you rely on useEffect
to update currentList
after sort
has been updated, you will get one render where they are mismatched. Just make a function / functions to set them both at once.
function setToPosted(){
setSort('posted');
setCurrentList({});
}
function setToAlphabetical(){
setSort('alphabetical');
setCurrentList([]);
}
Alternatively you can just check if the value is an array or not
<>
{
currentList && !Array.isArray(currentList) && Object.keys(currentList)
}
{
currentList && Array.isArray(currentList) && currentList.map
}
</>