9

For class component we can use

this._reactInternalFiber._debugOwner.type.name 

as mentioned in React Access parent component name.

But is there any way to do same in function component?

DonnyFlaw
  • 581
  • 3
  • 9
user3211534
  • 123
  • 1
  • 2
  • 6
  • If the child needs the name of the parent, you should pass it down as a prop. What problem are you trying to solve here? – Håken Lid Feb 17 '21 at 17:06
  • the name `_reactInternalFiber` gives you a clue that this is an internal mechanism and not a public api. That means that this should not be relied on, and the functionality might change between minor versions of react. There's probably a more idiomatic and simpler way to achieve your goal. – Håken Lid Feb 17 '21 at 17:10
  • 1
    By this logic, what's the use of the "function.caller" property which returns the function that invoked the specified function. We can simply pass function name as one of parameter. I want to get parent component name for debugging purpose and not for production. – user3211534 Feb 18 '21 at 05:40
  • I agree. By the same logic, you should avoid Function.caller. – Håken Lid Feb 18 '21 at 11:19
  • 2
    If any reusable component is used in 10-15 components and I want to identify, it is called from which component for debugging purpose. Then, how will I do it? – user3211534 Feb 18 '21 at 12:02

1 Answers1

0

Based on this answer you can make a custom hook to display the parent's name:

import { useEffect, useRef, useState } from "react";

function FindReact(dom, traverseUp = 0) {
  const key = Object.keys(dom).find((key) => {
    return (
      key.startsWith("__reactFiber$") || // react 17+
      key.startsWith("__reactInternalInstance$")
    ); // react <17
  });

  const domFiber = dom[key];
  if (domFiber == null) return null;

  // react <16
  if (domFiber._currentElement) {
    let compFiber = domFiber._currentElement._owner;
    for (let i = 0; i < traverseUp; i++) {
      compFiber = compFiber._currentElement._owner;
    }
    return compFiber._instance;
  }

  // react 16+
  const GetCompFiber = (fiber) => {
    //return fiber._debugOwner; // this also works, but is __DEV__ only
    let parentFiber = fiber.return;
    while (typeof parentFiber.type == "string") {
      parentFiber = parentFiber.return;
    }
    return parentFiber;
  };
  let compFiber = GetCompFiber(domFiber);
  for (let i = 0; i < traverseUp; i++) {
    compFiber = GetCompFiber(compFiber);
  }
  return compFiber;
}

const useParentName = () => {
  const ref = useRef();
  const [parentName, setParentName] = useState();
  useEffect(() => {
    if (ref.current) {
      let node = FindReact(ref.current, 1);
      setParentName(node.type.name);
    }
  }, []);

  return { ref, parentName };
};

const Child = () => {
  const { ref, parentName } = useParentName();

  return (
    <div ref={ref}>
      <div>{parentName}</div>
    </div>
  );
};

export default function App() {
  return (
    <div className="App">
      <Child />
    </div>
  );
}

But you will need to use ref inside the child component to display the parent's name

Andrey
  • 928
  • 1
  • 12
  • 20