React ref.current не определен в useLayoutEffect - PullRequest
0 голосов
/ 14 июля 2020

Я пытаюсь реализовать PO C для горизонтально прокручиваемого раздела в проекте. У меня есть 3 h3s рядом друг с другом над горизонтально прокручиваемой секцией, h3s должны соответствовать отдельным подразделам в горизонтальном бите.

Я использую react-crossction-Observer для создания ссылок на под- разделы, чтобы иметь возможность прокручиваться к ним, когда пользователь нажимает на один из h3s. Состояние устанавливается правильно, и в React Dev Tools я вижу, что хуки useInView устанавливаются правильно, а также отображают s как refs. Однако, когда я пытаюсь получить доступ к refOne.current где угодно, он возвращается undefined. Я явно использую useLayoutEffect здесь, чтобы дождаться, пока все узлы DOM будут полностью окрашены, но refOne.current все еще не определен.

import React, { useState, useLayoutEffect } from 'react';
import { useInView } from 'react-intersection-observer';
import classNames from 'classnames';

import classes from './Projects.module.css';
const Projects = () => {
    const [activeState, setActiveState] = useState('one');

    let [refOne, inViewOne, entryOne] = useInView({
        threshold: 1,
    });

    let [refTwo, inViewTwo, entryTwo] = useInView({
        threshold: 1,
    });

    let [refThree, inViewThree, entryThree] = useInView({
        threshold: 1,
    });

    useLayoutEffect(() => {

        console.log(refOne.current) // comes back undefined

        checkAndScroll(activeState);
    }, [activeState]);

    const setActiveHeading = (id) => {
        setActiveState(id);
    };

    let oneClasses = classNames(classes.heading, {
        [classes.activeHeading]: activeState === 'one',
    });
    let twoClasses = classNames(classes.heading, {
        [classes.activeHeading]: activeState === 'two',
    });
    let threeClasses = classNames(classes.heading, {
        [classes.activeHeading]: activeState === 'three',
    });

    const checkAndScroll = (id) => {

        console.log(refOne.current) // comes back undefined

        if (id === 'one' && !inViewOne) {
            scrollToRef(refOne);
        } else if (id === 'two' && !inViewTwo) {
            scrollToRef(refTwo);
        } else if (id === 'three' && !inViewThree) {
            scrollToRef(refThree);
        }
    };
    const scrollToRef = (ref) => {

        console.log(refOne.current) // comes back undefined

        if (ref && ref.current) {
            ref.current.scrollIntoView();
        }
    };

    return (
        <>
            <div className={classes.headingsContainer}>
                <h3
                    className={oneClasses}
                    id={classes.headingOne}
                    onClick={() => setActiveHeading('one')}
                >
                    One
                </h3>
                <h3
                    className={twoClasses}
                    id={classes.headingTwo}
                    onClick={() => setActiveHeading('two')}
                >
                    Two
                </h3>
                <h3
                    className={threeClasses}
                    id={classes.headingThree}
                    onClick={() => setActiveHeading('three')}
                >
                    Three
                </h3>
            </div>
            <div className={classes.container}>
                <div ref={refOne} className={classes.one} />
                <div ref={refTwo} className={classes.two} />
                <div ref={refThree} className={classes.three} />
            </div>
        </>
    );
};

export default Projects;

Я работал над этим часами, и я в конце моего ума. Любая помощь приветствуется!

Ответы [ 2 ]

0 голосов
/ 14 июля 2020

Я, наконец, понял это, и это чертовски глупо.

Хук реагировать-пересечение-наблюдатель предоставляет ссылку, логическое значение inView и объект входа. Однако ref на самом деле не является ссылкой.

ref - это функция обратного вызова , которая не содержит текущего свойства (следовательно, undefined). См. Комментарий создателя здесь: https://github.com/thebuilder/react-intersection-observer/issues/285#issuecomment -572980628

Вместо этого вы должны использовать возвращаемый объект ввода и получить доступ к целевому свойству. Если вы правильно назначили свои ссылки, entry.target будет содержать узел html, которому вы назначили ссылку.

0 голосов
/ 14 июля 2020

Я явно использую useLayoutEffect здесь, чтобы дождаться, пока все узлы DOM будут полностью окрашены.

Обновления, запланированные внутри useLayoutEffect, будут сброшены синхронно, до того, как браузер возможность рисовать .

React docs говорит об useLayoutEffect.

Вы пробовали useEffect вместо useLayoutEffect?

...