React Anchor Link on Hidden Item - Can't perform a React state update on an unmounted component

Viewed 33

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>
  )
}
0 Answers
Related