简体   繁体   中英

Multiple refs in react

I have a Container, that should have references to some of it's children components:

const Container = () => {
  const blocks: HTMLDivElement[] = [];

  return (
    <div>
      <Navigation currentBlock={currentBlock} blocks={blocks} />
      <div ref={(ref) => ref && blocks.push(ref)}>
        // ...
      </div>
      <div ref={(ref) => ref && blocks.push(ref)}>
        // ...
      </div>
      <div ref={(ref) => ref && blocks.push(ref)}>
        // ...
      </div>
      <div ref={(ref) => ref && blocks.push(ref)}>
        // ...
      </div>
    </div>
  );
};

But, when I try to render Navigation component, the blocks variable is an empty array.

I tried converting blocks variable to a reference using useRef hook:

const Container = () => {
  const blocks = useRef<HTMLDivElement[]>([]);

  return (
    <div>
      <Navigation currentBlock={currentBlock} blocks={blocks.current} />
      <div ref={(ref) => ref && blocks.current.push(ref)}>
        // ...
      </div>
      <div ref={(ref) => ref && blocks.current.push(ref)}>
        // ...
      </div>
      <div ref={(ref) => ref && blocks.current.push(ref)}>
        // ...
      </div>
      <div ref={(ref) => ref && blocks.current.push(ref)}>
        // ...
      </div>
    </div>
  );
};

blocks is still an empty array on render, but after that it becomes a valid array of references that I wanted.

Is there any way to update Navigation component without rerendering Container ?

EDIT : Here's my Navigation component:

const Navigation = ({ currentBlock, blocks }: { currentBlock: number, blocks: MutableRefObject<HTMLDivElement[]>}) => {
  console.log(blocks.current);
  return (
    <nav>
      {blocks.current.map((_, idx) => (
        <NavigationLink key={idx} active={currentBlock === idx} />
      ))}
    </nav>
  );
}

In my console, I have this output:

截屏

The Navigation component doesn't render any NavigationLink s, as if the array is empty.

To store the refs, you should use the useRef hook. However you must pass on the refs to another component, not by using blocks.current but just blocks. This way it would ensure that the props used by the navigation component can then access the mutated properties since a re-render is not triggered when the refs are assigned

const Container = () => {
  const blocks = useRef<HTMLDivElement[]>([]);

  return (
    <div>
      <Navigation currentBlock={currentBlock} blocks={blocks} />
      <div ref={(ref) => ref && blocks.current.push(ref)}>
        // ...
      </div>
      <div ref={(ref) => ref && blocks.current.push(ref)}>
        // ...
      </div>
      <div ref={(ref) => ref && blocks.current.push(ref)}>
        // ...
      </div>
      <div ref={(ref) => ref && blocks.current.push(ref)}>
        // ...
      </div>
    </div>
  );
};

Now inside the Navigation component you can make use of props.blocks.current

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM