I've got a React app with URLs defined with React Router:
const App: React.FC = (): JSX.Element => {
return (
<Router>
<Switch>
<Redirect exact from="/" to="/rules" />
<Route
exact
path={["/rules", "/rules/:placeId"]}
component={LandingPage}
/>
<Route
exact
path={["/route", "/route/:start/:end"]}
component={RoutePage}
/>
</Switch>
</Router>
);
};
I want to allow the user to go to a specific accordion of the document if the url contains a hash part like this /rules/someplace#accordion-3
I have a component that returns the accordions in question, which all have an id:
const CategoryDisplay: React.FC<Props> = (props) => {
...
return (
<>
<Accordion
id={`category-${accordion.id}`}/>
</>
);
};
export default CategoryDisplay;
And when I open an URL with an anchor like /rules/someplace#accordion-3
while I'm already on the page, everything works fine and it scrolls to the element. However, on the initial load of the page, this behavior doesn't work.
How would I go about scrolling to the element only after the page has loaded?
I think the idea would be to use an effect to scroll to the appropriate component after the component mounts. Perhaps something like this:
React.useEffect(() => {
const anchor = window.location.hash.slice(1);
if (anchor) {
const anchorEl = document.getElementById(anchor);
if (anchorEl) {
anchorEl.scrollIntoView();
}
}
}, []);
Notes:
I don't know if I understand correctly.
I think, you should make a function for wait everything complete.
but, if you can't catch exactly timing when everything fine, you can use trick.
example :
const CategoryDisplay: React.FC<Props> = (props) => {
...
const [accordionId, setAccordionId] = useState("");
useEffect(()=>{
// this component mounted
...
setTimeout(()=>{
// do something
setAccordionId(`category-${accordion.id}`);
},0);
}, []);
return (
<>
<Accordion
id={accordionId}/>
</>
);
};
This will definitely run in the frame after the component mounted.