Laurie Vince
Laurie Vince

Reputation: 133

React Hooks - How to target an element child (with useRef) with a variable declaration outside of useEffect?

I'm experimenting with React Hooks and I'm wondering how to target elements children with useRef. Actually, I know how to target an element with useRef. But I meet some problems when I'm trying to assign children to a variable.

Here's an example :

import React, { useState, useEffect, useRef } from "react";
import "./styles.css";

export default function App() {
  let containerRef = useRef(null);

  let title, subtitle;

  const myEvent = () => {
    console.log(title);
  };

  useEffect(() => {
    title = containerRef.children[0];
    subtitle = containerRef.children[1];
  }, []);

  return (
    <div className="App" ref={el => (containerRef = el)}>
      <h1 onClick={myEvent}>Hello World!</h1>
      <h2>What's going on ?</h2>
    </div>
  );
}

I would like to access to the title and subtitle variables to create a function outside of useEffect. I know I'm wrong about the first declaration of title and subtitle. But actually I don't know how to fix this. I tried to use useState, but I failed to resolve my problem.

(Precisions : of course, in my real project, I just don't want display the variable in the console).

Can someone help me to fix this ?

Upvotes: 5

Views: 29459

Answers (3)

Anas Alhariri
Anas Alhariri

Reputation: 1

If you wish to access a child using the name attribute instead of the index; you could do it the following way:

import React, { useState, useEffect, useRef } from "react";
import "./styles.css";

export default function App() {
  let containerRef = useRef(null);
  const [title, setTitle] = useState("");

  const myEvent = () => {
    console.log(title);
  };

  useEffect(() => {
    setTitle(containerRef.current.children['element_name_attribute']);
    //OR:
    setTitle(containerRef.current.children.element_name_attribute);
  }, []);

  return (
    <div className="App" ref={containerRef}>
      <h1 name="element_name_attribute" onClick={myEvent}>Hello World!</h1>
      <h2>What's going on ?</h2>
    </div>
  );
}

Upvotes: 0

Muhammad Zeeshan
Muhammad Zeeshan

Reputation: 4748

You need to target your current HTML element and then get children like:

import React, { useState, useEffect, useRef } from "react";
import "./styles.css";

export default function App() {
  let containerRef = useRef(null);
  const [title, setTitle] = useState("");

  const myEvent = () => {
    console.log(title);
  };

  useEffect(() => {
    setTitle(containerRef.current.children[0]);
  }, []);

  return (
    <div className="App" ref={containerRef}>
      <h1 onClick={myEvent}>Hello World!</h1>
      <h2>What's going on ?</h2>
    </div>
  );
}

This will log children to the console. Hope this will help you.

Upvotes: 9

fxdxpz
fxdxpz

Reputation: 1989

You can use useRef to store some object between renders:

import React, { useRef, useEffect } from "react";
import "./styles.css";

export default function App() {
  const containerRef = useRef(null);
  const titleRef = useRef(null);
  const subtitleRef = useRef(null);

  const myEvent = () => {
    console.log(titleRef.current);
  };

  useEffect(() => {
    titleRef.current = containerRef.current.children[0];
    subtitleRef.current = containerRef.current.children[1];
  }, []);

  return (
    <div className="App" ref={containerRef}>
      <h1 onClick={myEvent}>Hello World!</h1>
      <h2>What's going on ?</h2>
    </div>
  );
}

CodeSandbox: https://codesandbox.io/s/jovial-sound-e0eq2

Upvotes: 4

Related Questions