Reputation: 13
I am using an array of links to paginate because I want them in a specific order. This all works fine, if I navigate to any of the features pages I can paginate through them; but if I refresh a page the Next href defaults to [0] or 'features/safety-training' and Prev ends up being undefined. I am assuming this is something to do with how useEffect works but I am not sure how to fix it.
const [position, setPosition] = useState(null);
const [next, setNext] = useState(null);
const [prev, setPrev] = useState(null);
let theArray =[
"/features/safetytraining",
"/features/certificatetracking",
"/features/policies",
"/features/standard-operating-procedures",
"/features/competencies",
"/features/contractor-orientations",
"/features/worksite-screening",
"/features/inspections",
"/features/incident-reporting",
"/features/behavior-observations",
"/features/bulletins",
"/features/suggestions",
"/features/polls",
"/features/whistleblower"
]
useEffect(() => {
let pathname = window.location.pathname
//Check the array for pathname
let checkPosition = theArray.indexOf(pathname);
//Set the position to pathname index
setPosition(checkPosition)
});
//Update next/prev when position changes
useEffect(() => {
setNext(theArray[position +1])
setPrev(theArray[position -1])
}, [position]);
Here's the links:
<>
<button
style={{marginRight: '15px'}}>
<Link to={prev}>Prev</Link>
</button>
<button>
<Link to={next}>Next</Link>
</button>
</>
Upvotes: 1
Views: 276
Reputation: 80041
You don’t need state or side effects (useEffect
) for any of this:
// Pages don't change and don't depend on props or state,
// so let's define w/ `const` and extract from the
// component to avoid recreating on each render:
const pages = [
"/features/safetytraining",
"/features/certificatetracking",
"/features/policies",
"/features/standard-operating-procedures",
"/features/competencies",
"/features/contractor-orientations",
"/features/worksite-screening",
"/features/inspections",
"/features/incident-reporting",
"/features/behavior-observations",
"/features/bulletins",
"/features/suggestions",
"/features/polls",
"/features/whistleblower",
];
const Example = () => {
// This is extraordinarily cheap to compute and will not
// change without a re-render occurring, so we don't need
// for it to be state:
const position = typeof window === "undefined"
? 0
: pages.indexOf(window.location.pathname);
// Avoid using an invalid index position
const prevPath = position <= 0 ? pages[pages.length] : pages[position - 1];
const nextPath = position >= pages.length - 1 ? pages[0] : pages[position];
return (
<div>
<button style={{ marginRight: "15px" }}>
<Link to={prevPath}>Prev</Link>
</button>
<button>
<Link to={nextPath}>Next</Link>
</button>
</div>
);
};
Your original code was creating a number of issues:
setPosition
) React queues a re-render of the componentposition
, prev
, and next
were all null
useEffect
is not called, so your links would be broken on the initial loaduseEffect
hooks would be called
setPosition
, prompting a re-render where position
was set (prev
and next
would still be null
); since there is no dependency array, the first hook is called again, and setPosition
is called againposition
changed and call setPrev
and setNext
, prompting two more re-rendersprev
would be set but next
would not benext
would finally be set as expectedUpvotes: 1