Кажется, что useEffect срабатывает до завершения рендеринга - PullRequest
0 голосов
/ 01 апреля 2020

У меня есть этот компонент React, где я пытаюсь переместить фокус на определенный c div после того, как компонент завершил рендеринг.

Я попытался отладить в своем браузере, и containerRef - это никогда не устанавливается. Когда я приостанавливаю выполнение в строке, которая гласит: if (containerRef.current) {, я также вижу, что компонент еще не визуализирован. И компонент в настоящее время отображается только один раз (передавая жестко закодированные данные в Storybook, но также пытался смоделировать их внутри реального приложения, думая, что некоторый компонент-обертка в Storybook может каким-то образом вызывать зацепку).

Любые предположения, почему это может быть?

export function DuplicateSelect(props: DuplicateSelectProps) {
  const containerRef = useRef(null);

  useEffect(() => {
    if (containerRef.current) {
      containerRef.current.focus();
    }
  });

  return (
    <Overlay isOpen={true}>
      <div className="flex-center">
        <Card className="duplicate-select" elevation={1}>
          <div
            className="duplicate-select-options"
            tabIndex={0}
            ref={containerRef}
          >
            {props.results.map((result) => (
              <Item data={result} />
            ))}
          </div>
        </Card>
      </div>
    </Overlay>
  );
}

Сделал прототип в Codesandbox, и он отлично работает: https://codesandbox.io/s/damp-dust-4xiv0

Ответы [ 2 ]

1 голос
/ 02 апреля 2020

Я использую Blueprint. js в качестве библиотеки пользовательского интерфейса, и при дальнейших исследованиях я обнаружил, что проблема связана с визуализацией компонента <Overlay> внутри портала. Была опора, чтобы отключить это поведение, и это решило проблему. Похоже, что refs break при использовании порталов?

export function DuplicateSelect(props: DuplicateSelectProps) {
  const containerRef = useRef(null);

  useEffect(() => {
    if (containerRef.current) {
      containerRef.current.focus();
    }
  });

  return (
    <Overlay isOpen={true} usePortal={false} >
      <div className="flex-center">
        <Card className="duplicate-select" elevation={1}>
          <div
            className="duplicate-select-options"
            tabIndex={0}
            ref={containerRef}
          >
            {props.results.map((result) => (
              <Item data={result} />
            ))}
          </div>
        </Card>
      </div>
    </Overlay>
  );
}
0 голосов
/ 01 апреля 2020

Добавьте второй аргумент в useEffect ловушку, чтобы он срабатывал, когда этот ref будет установлен

useEffect(() => {
    if (containerRef.current) {
      containerRef.current.focus();
    }
 }, [containerRef.current]);
...