I've created a section on a site that is two sliders, the first slider is visible and on click the slide will display the corresponding slide beneath with the bottom slider initially starting as a display: none element. Each top slide also has a button on it that will anchor you down to the bottom slider to put it in a better view position.
If you navigate from the homepage onto this page and click on the anchor button first to display the content, the page does anchor down slightly but the content does not display, it also pastes the anchor link into the URL which doesn't seem to be how the working version behaves. On load the page is getting an error in the console saying Can't perform a React state update on an unmounted component.
You then have to click the object again or reload the page to get the anchor function/content to display as expected. Reloading the page also removes the React state console error as I'm assuming the component does mount.
The slider is built using Slick React slider and I'm using Gatsby Anchor Link Plugin and React Animate Height to perform both the hide/show height and anchor functions as I learnt in the project you can't just add a class to add height or just anchor stuff in React which is fun/backwards.
The component class for the page and the 2 components are below:
class AboutPage extends React.Component {
_isMounted = false;
constructor(props) {
super(props)
this.heroTextRef = React.createRef()
this.teamRef = React.createRef()
this.serviceGroupsRef = React.createRef()
this.state = {
nav1: null,
nav2: null,
isShow: false,
height: 0,
activeColor: false
}
this.openHeight = this.openHeight.bind(this);
this.closeHeight = this.closeHeight.bind(this);
}
openHeight = () => {
const { height } = this.state;
const { activeColor } = this.state;
this.setState({
height: 'auto',
activeColor: true,
});
};
closeHeight = () => {
const { height } = this.state;
const { activeColor } = this.state;
this.setState({
height: 0,
activeColor: false,
});
};
componentDidMount() {
this.setState({
nav1: this.slider1,
nav2: this.slider2
});
this._isMounted = false;
}
render() {
const { height } = this.state;
const team = get(this, 'props.data.contentfulPageContentStudio.theOrcaTeam')
return (
<Layout
location={this.props.location}
inversionRefs={[this.serviceGroupsRef, this.teamRef]}
>
<SEO
siteTitle={'About Us - ' + siteTitle}
/>
<TeamWrapper ref={this.teamRef} ref={this.serviceGroupsRef}>
<Container width={14}>
<Reveal
fraction={ANIMATION.revealFriction}
keyframes={customReveal}
triggerOnce
>
<TeamGridTitle id="topSlider">The Orca Team</TeamGridTitle>
</Reveal>
<Slider
dots={false}
infinite={false}
speed={500}
slidesToShow={3}
slidesToScroll={1}
swipeToSlide={true}
arrows={false}
asNavFor={this.state.nav2}
focusOnSelect={true}
responsive={[
{
breakpoint: 1024,
settings: {
slidesToShow: 2
}
}
]}
ref={slider => (this.slider1 = slider)}
className="top-slider"
>
{team.map((person, i) => (
<>
<TeamCard key={slugify(person.firstName)} index={i} person={person} onClick={this.openHeight} colour={this.state.activeColor}/>
</>
))}
</Slider>
</Container>
<AnchorTag id="bottomSlider" />
<AnimateHeight
duration={ 500 }
height={ height }
>
<SliderContainer>
<Slider
asNavFor={this.state.nav1}
ref={slider => (this.slider2 = slider)}
slidesToShow={1}
fade={true}
adaptiveHeight={true}
arrows={false}
dots={false}
infinite={false}
>
{team.map((person, i) => (
<>
<PersonBio key={slugify(person.lastName)} index={i} person={person} onClick={this.closeHeight}/>
</>
))}
</Slider>
</SliderContainer>
</AnimateHeight>
</TeamWrapper>
</Layout>
)
}
}
Top Slider Component:
const TeamCard = (props) => {
return (
<Card
onClick={props.onClick}
className={props.colour ? 'team-card' : null}
>
{props.person.image && <Img fluid={props.person.image.fluid} />}
<Info image={props.person.image} className="card-item">
<Name>
{props.person.firstName} {props.person.lastName}
</Name>
<Role className="small">{props.person.role}</Role>
<AnchorLink
to="/about/#bottomSlider"
title="Top Link"
>
<DownArrow version="1.1" x="0px" y="0px" viewBox="0 0 64 64" width="24" height="24">
<polyline
fill="none"
stroke="#FFFFFF"
strokeWidth="8"
strokeMiterlimit="10"
points="3.3,17.2 32,46.8 60.7,17.2 "/>
</DownArrow>
</AnchorLink>
</Info>
</Card>
)
}
Bottom Slider Component:
const PersonBio = (props) => {
return (
<Card className="card-block">
<Info>
<Container width={14}>
<FlexRow>
<PersonInfo>
<Name>
{props.person.firstName} {props.person.lastName}
</Name>
<Role className="small">{props.person.role}</Role>
<Meta>
{props.person.dribble && (
<IconLink
href={props.person.dribble}
target="_blank"
rel="noreferrer"
>
<IconDribbleSVG
alt={`${props.person.firstName} ${props.person.lastName} Dribbble link`}
/>
</IconLink>
)}
{props.person.instagram && (
<IconLink
href={props.person.instagram}
target="_blank"
rel="noreferrer"
>
<IconInstagramSVG
alt={`${props.person.firstName} ${props.person.lastName} Instagram link`}
/>
</IconLink>
)}
{props.person.linkedIn && (
<IconLink
href={props.person.linkedIn}
target="_blank"
rel="noreferrer"
>
<IconLinkedInSVG
alt={`${props.person.firstName} ${props.person.lastName} LinkedIn link`}
/>
</IconLink>
)}
</Meta>
</PersonInfo>
<PersonContent className="bio-text" dangerouslySetInnerHTML={{ __html: props.person.bio.bio }}>
</PersonContent>
</FlexRow>
<SvgRow>
<AnchorLink
to="/about/#topSlider"
title="Bottom Link"
>
<CloseBio x="0px" y="0px" viewBox="0 0 64 64" className="bio-close" onClick={props.onClick}>
<circle cx="32" cy="32" r="29.8"/>
<line x1="12.7" y1="32" x2="51.3" y2="32" className="crossLine1"/>
<line x1="12.7" y1="32" x2="51.3" y2="32" className="crossLine2"/>
</CloseBio>
</AnchorLink>
</SvgRow>
</Container>
</Info>
</Card>
)
}