Reputation: 5245
I would like to know how to use React refs
to navigate to a specific component
function App() {
let CompetencesRef = React.createRef();
let ExperiencesRef = React.createRef();
let FormationRef = React.createRef();
let RecoRef = React.createRef();
let refs = { CompetencesRef, ExperiencesRef, FormationRef, RecoRef }
let scrollToRef = (reference) => {
console.log(reference)
reference.current.scrollIntoView({ behavior: 'smooth' })
}
return (
<ParallaxProvider>
<ThemeProvider theme={theme}>
<div className="App">
<div className="hero">
<HeaderApp refs={refs} scrollToRef={scrollToRef} />
<ApprochApp />
</div>
<Apropos />
<Competences ref={CompetencesRef} />
<Experiences ref={ExperiencesRef} />
<Formation ref={FormationRef} />
<Recom ref={RecoRef} />
<Contact />
<Footer />
</div >
</ThemeProvider>
</ParallaxProvider>
);
}
export default App;
AppHeader
const AppHeader = (props, refs, scrollToRef) => {
console.log(props)
return (
<div >
<Headroom>
<MenuApp refs={props.refs} scrollToRef={props.scrollToRef} />
</Headroom>
</div>
)
}
export default AppHeader
AppMenu
const MenuApp = (props, refs, scrollToRef) => {
console.log(props)
return (
<div className="menu sticky-inner grid-container">
<div className="desktop-menu">
<div className="menu-item a-propos" ref={props.refs.CompetencesRef} onClick={() => props.scrollToRef(props.refs.CompetencesRef)}>
<p className='button'>Compétences</p>
</div>
<div className="menu-item competences" ref={props.refs.ExperiencesRef} onClick={() => props.scrollToRef(props.refs.ExperiencesRef)} >
<p className='button'>Experiences </p>
</div>
<div className="menu-item experiences" ref={props.refs.FormationRef} onClick={() => props.scrollToRef(props.refs.FormationRef)}>
<p className='button'>Formation</p>
</div>
<div className="menu-item formation" ref={props.refs.RecoRef} onClick={() => props.scrollToRef(props.refs.RecoRef)}>
<p className='button'>Recomendations </p>
</div>
</div>
<p className="mobile-menu">
<MenuIcon />
</p>
<div className="github-ico">
<GitHubIcon />
</div>
<div className="linkedin-ico">
<LinkedInIcon />
</div>
<div className="contact">
<div className='contact-btn'>
<span className="contact-ico"> <MessageIcon /></span> <span style={isBrowser ? { display: 'block' } : { display: 'none' }} > contact </span>
</div>
</div>
</div>
)
}
export default React.forwardRef(MenuApp)
I'm using a ClickHandler in Apps.js with scrollIntoView
. But actually when I click view does not scroll.
I would not use packages like react-scroll
Upvotes: 0
Views: 1613
Reputation: 6631
There are two problems in your code:
First, there is a difference in using ref
for function components and class components. Using ref
on functional components will yield an unexpected result because they don't have an instance.
You should be using forwardRef
for all section components and make sure the ref
is placed on the wrapping element.
The second problem is that you are using the refs for two components. Refs should only be assigned to a single component (maybe not in all cases). In this case, you want a reference to the section components to get a hold on the HTML element.
So remove the ref
props in the AppMenu component:
<div className="menu-item a-propos" onClick={() => props.scrollToRef(props.refs.CompetencesRef)}>
<p className='button'>Compétences</p>
</div>
Although it will work with refs, you might be considering an easier setup. E.g. by using id's.
If you do want to keep using refs, I would also suggest that you don't pass the refs object to child components. You actually don't want the child component to "know" about higher components in the tree.
For example, you can mitigate this by handling the onClick callback in the App component.
Upvotes: 1
Reputation: 53884
Here is a minimal reproducible example (without all code noise):
function App() {
const competencesRef = React.useRef();
const refs = { competencesRef /* ExperiencesRef, FormationRef, RecoRef */ };
const scrollToRef = (reference) => {
reference.current.scrollIntoView({ behavior: "smooth" });
};
return (
<>
<AppHeader refs={refs} scrollToRef={scrollToRef} />
<Competences ref={competencesRef} />
</>
);
}
const Competences = React.forwardRef((props, ref) => {
return <div ref={ref}>...</div>;
});
const AppHeader = (props) => {
return <MenuApp refs={props.refs} scrollToRef={props.scrollToRef} />;
};
const MenuApp = (props) => {
return (
<div
ref={props.refs.competencesRef}
onClick={() => props.scrollToRef(props.refs.competencesRef)}
>
<p className="button">Compétences</p>
</div>
);
};
The problem with your code is that you use React.createRef
instead of React.useRef
(you can search for the differences), and you need React.forwardRef
only for components using the ref
prop like Competences
.
Upvotes: 2
Reputation: 1534
Try this in your scrollToRef
function:
window.scrollTo(0, reference.current.offsetTop);
Upvotes: -1