Reputation: 327
I have a sticky navigation in this app I'm building using React. What I'm trying to figure out is how can I scroll to that div using an onClick
? I'm using the window.scrollTo
method.
The divs on the page have corresponding IDs to the anchor tags.
handleClick = e => {
this.setState({
activeSection: e.target.id,
});
let sections = document.querySelectorAll('.deal-details__container');
window.scrollTo({
top: 690,
behavior: 'smooth',
});
};
My markup looks like this:
<h6 className="section-header-overview text-center mb-0">
<a href="#overview" className={ this.state.activeSection === true ? 'active' : ''} onClick={() => this.handleClick('overview')}>
Overview
</a>
Here is one of the components I need to scroll to:
import React from 'react';
import { dealType } from '../../../../core/types';
import SpecsGroup from './SpecsGroup';
import SpecsTabButton from './SpecsTabButton';
import { Row, Col, Container } from 'reactstrap';
import { groupBy, filter, map, toPairs, pipe, prop, zipObj } from 'ramda';
export default class Specs extends React.PureComponent {
scrollRef = React.createRef();
static propTypes = {
deal: dealType.isRequired,
};
state = {
activeTab: 'capabilities',
activeCategory: null,
};
filterSpecs() {
const groupByCategories = pipe(
filter(item => {
if (
this.state.activeTab === 'capabilities' &&
capabilitiesCategories.includes(item.category)
) {
return true;
}
if (
this.state.activeTab === 'features' &&
featuresCategories.includes(item.category)
) {
return true;
}
return false;
}),
groupBy(prop('category')),
toPairs,
map(zipObj(['category', 'values']))
);
return groupByCategories(this.props.deal.equipment);
}
toggleActiveTab(tab) {
if (this.state.activeTab !== tab) {
this.setState({
activeTab: tab,
activeCategory: null,
});
}
}
toggleActiveCategory(category) {
if (this.state.activeCategory !== category) {
this.setState({
activeCategory: category,
});
} else {
this.setState({
activeCategory: null,
});
}
}
render() {
if (
!this.props.deal.equipment ||
this.props.deal.equipment.length === 0
) {
return false;
}
return (
<div className="deal-details__container pt-5 pb-5" id="specs" ref={this.scrollRef}>
<Container>
<Row className="deal__section-heading" noGutters>
<Col>
<h3 className="text-center"> Specifications </h3>
</Col>
</Row>
<Row className="rounded bg-white shadow-sm" noGutters>
<Col>
<Row className="deal-details__specs-tabs" noGutters>
<SpecsTabButton
isActive={
this.state.activeTab === 'capabilities'
}
label="Capabilities"
value="capabilities"
handleOnClick={this.toggleActiveTab.bind(
this
)}
/>
<SpecsTabButton
isActive={
this.state.activeTab === 'features'
}
label="Features"
value="features"
handleOnClick={this.toggleActiveTab.bind(
this
)}
/>
</Row>
<SpecsGroup
deal={this.props.deal}
category={this.state.activeTab}
activeCategory={this.state.activeCategory}
specs={this.filterSpecs()}
toggleActiveCategory={this.toggleActiveCategory.bind(
this
)}
/>
</Col>
</Row>
</Container>
</div>
);
}
}
I'm still learning react and JS in general. So I may be doing this completely wrong. I've read about refs, but not sure if those would be better/worse.
Any and all help is appreciated!
Upvotes: 6
Views: 38140
Reputation: 116
If the reference is for a class component present inside the parent container where the OnClick event is fired, you will need to pass the reference as props to the child component. And then, use 'ref' attribute in the main div of the component.
Upvotes: 0
Reputation: 15688
You can use React's ref system which gives you access to DOM elements and manipulation.
So in your code you can do something like this:
class myComponent extends React.Component{
constructor(props){
super(props)
this.state = {
field: value
}
//creates a reference for your element to use
this.myDivToFocus = React.createRef()
}
handleOnClick = (event) => {
//.current is verification that your element has rendered
if(this.myDivToFocus.current){
this.myDivToFocus.current.scrollIntoView({
behavior: "smooth",
block: "nearest"
})
}
}
render(){
return(
<button onClick={this.handleOnClick}>Click me</button>
<div ref={this.myDivToFocus}>
Welcome to my section
</div>
)
}
}
Upvotes: 21