Joe C
Joe C

Reputation: 1855

ReactJS - how to create a dynamic ref from the parent. The child is a functional component

Here is the child:

import React from 'react';

const Hero = (props) => (
  <div ref={props.heroRef} className={`hero-region ${props.class}`}>
    <h3>{props.copy}</h3>
  </div>
);

export default Hero;

Here is the parent:

import React, { Component, Fragment } from "react";
import Hero from "./../components/content/Hero";

export default class HomePage extends Component {
  render() {
    const createHeroNodes = () =>
      [
        { class: "light", copy: "first div" },
        { class: "dark", copy: "second div" }
      ].map((hero, i) => (
        <Hero
          heroRef={el => (this[`${heroRegion}${i}`] = el)}
          class={hero.class}
          copy={hero.copy}
        />
      ));

    return <Fragment>{createHeroNodes()}</Fragment>;
  }
}

I expect it to create child refs that are accessible like this.heroRegion1, and this.heroRegion2 so I can do some imperative animation on scrolling.

What I'm getting back is an error: 'heroRegion is not defined'

Any ideas? I am trying to avoid hard-coding this.heroRegion1 to this.heroRegion(...n).

Upvotes: 1

Views: 287

Answers (1)

Tholle
Tholle

Reputation: 112777

By writing ${heroRegion} inside the template literal you are trying to access a heroRegion variable, which does not exist.

You can just write heroRegion${i} instead and it will work as expected.

Example

const Hero = props => (
  <div ref={props.heroRef} className={`hero-region ${props.class}`}>
    <h3>{props.copy}</h3>
  </div>
);

class HomePage extends React.Component {
  componentDidMount() {
    console.log(this.heroRegion0, this.heroRegion1);
  }

  render() {
    return (
      <React.Fragment>
        {[
          { class: "light", copy: "first div" },
          { class: "dark", copy: "second div" }
        ].map((hero, i) => (
          <Hero
            heroRef={el => (this[`heroRegion${i}`] = el)}
            class={hero.class}
            copy={hero.copy}
          />
        ))}
      </React.Fragment>
    );
  }
}

ReactDOM.render(<HomePage />, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

<div id="root"></div>

Upvotes: 1

Related Questions