skip to Main Content

Is it safe to do this:

function Parent() {
  const myRef = useRef([1, 2, 3]);
  console.log("parent: " + myRef.current);
  return <Child myList={myRef.current} />;
}

function Child({ myList }) {
  const [currInt, setCurrInt] = useState(4);
  console.log("child: " + myList);
  return (
    <Button
      onClick={() => {
        myList.push(currInt);
        setCurrInt((n) => n + 1);
      }}
    />
  );
}

Output:

parent: 1,2,3
child: 1,2,3
<click>
child: 1,2,3,4
<click>
child: 1,2,3,4,5
...

I know the parent won’t rerender upon updates of myList and that is the expected behavior.
I just wonder if this goes against any kind of React principles or could break in the future.

Previously I had stored the initial list passed down from Parent in another ref inside the Child component and this worked as well. However, it does not seem to be necessary if I can just mutated the parent ref object.

2

Answers


  1. Why it’s feasible

    Actually, if you consider this situation purely from a JavaScript perspective, there’s no issue because the Child and Parent components share the same object. This object’s memory address remains unchanged upon the Parent’s re-render, thanks to the use of useRef.

    Why not

    However, adopting this approach may lead to confusion regarding the data flow. In React, I recommend employing pure functions to ensure a clear and predictable data stream. It’s advisable to avoid ambiguous data transfers as much as possible. I believe that the key to efficient development lies in making the codebase easily maintainable and update-friendly.

    Summary

    Although this violates some of React’s core principles, such as data flowing down from parent to child, this capability is necessary in certain scenarios. Therefore, it exists as an escape hatch.

    Login or Signup to reply.
  2. To get this done you need to wrap the Child inside forwardRef & pass the take ref object as a prop.

    & for advance functionality you can use useImperativeHandle hooks.

    https://react.dev/reference/react/forwardRef

    https://react.dev/reference/react/useImperativeHandle

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search