I have component
import React, { useState, useEffect } from "react";
import { useParams } from "react-router-dom";
const data = {
"1": ["1a", "1b"],
"2": ["2a"]
};
const slugs = {
"1a": { text: "Lorem" },
"1b": { text: "ipsum" },
"2a": { text: "..." }
};
const ExamplePage: React.FC = () => {
const { id } = useParams<{ id: string }>();
const [index, setIndex] = useState(0);
useEffect(() => {
setIndex(0);
}, [id]);
console.log("state", {
id,
index
});
const slug = data[id][index];
const text = slugs[slug].text;
function onPrev(): void {
if (index <= 0) {
return;
}
setIndex((index) => index - 1);
}
function onNext(): void {
if (index >= data[id].length - 1) {
return;
}
setIndex((index) => index + 1);
}
return (
<div>
<button onClick={onPrev}>Prev</button>
<span>{text}</span>
<button onClick={onNext}>Next</button>
</div>
);
};
export default ExamplePage;
And Route for this:
<Route path="/:id" component={ExamplePage} />
Live version: https://codesandbox.io/s/react-hooks-ewl4d
There is a bug with this code when:
- User is on
/1url - User clicks button "Next"
- User clicks link to
/2url
In this case id will be "2", index will be 1, but there isn't data["2"][1].
As you can see useEffect don't help in this case because useEffect don't stop current function call.
My question is: How I can ensure that this state will be always correct?
I know that I can write const text = slugs[slug]?.text; and this solve my bug, but still, in one moment, component have incorrect state. I wondering if is a way to prevent this incorrect state.
In React class component this problem can be solved by getDerivedStateFromProps - You can see this live on https://codesandbox.io/s/react-hooks-solve-in-react-component-xo43g