使用useRef的React自定义Hook首次调用组件加载时会返回null?

时间:2019-11-22 19:38:18

标签: reactjs react-hooks

我创建了一个自定义钩子,以在滚动组件时将元素滚动回到视图中。

export const useComponentIntoView = () => {
  const ref = useRef();
  const {current} = ref;
  if (current) {
    window.scrollTo(0, current.offsetTop );
  }
  return ref;
}

现在,我在

这样的功能组件中使用了此功能
<div ref={useComponentIntoView()}>

因此,第一次电流总是为null,我知道该组件仍未安装,因此该值为null。但是我们总是可以在我的自定义钩子中取得这个值的原因,因为仅对于第一次导航,组件滚动不起作用。有没有解决这个问题的办法。

2 个答案:

答案 0 :(得分:1)

我们已经从ref中读取了useEffect,如果已经分配了它。要仅在安装时调用它,我们传递一个空的依赖项数组:

const MyComponent = props => {
    const ref = useRef(null);

    useEffect(() => {
        if (ref.current) {
            window.scrollTo(0, ref.current.offsetTop);
        }
    }, []);

    return <div ref={ref} />;
};

为了在组件本身中拥有此功能,我们可以采用以下方式:

const useComponentIntoView = () => {
    const ref = useRef(null);

    useEffect(() => {
        if (ref.current) {
            window.scrollTo(0, ref.current.offsetTop);
        }
    }, []);

    return ref;
};

const MyComponent = props => {
    const ref = useComponentIntoView();

    return <div ref={ref} />;
};

在进行某些更改后,我们也可以运行useEffect钩子。在这种情况下,我们需要将其传递给依赖项数组,该数组属于一个状态。此变量可以属于同一Component或祖先。例如:

const MyComponent = props => {
    const [counter, setCounter] = useState(0);
    const ref = useRef(null);

    useEffect(() => {
        if (ref.current) {
            window.scrollTo(0, ref.current.offsetTop);
        }
    }, [counter]);

    return (
        <div ref={ref}>
            <button onClick={() => setCounter(counter => counter + 1)}>
                Click me
            </button>
        </div>
    );
};

在上面的示例中,每次单击按钮都会更新计数器状态。此更新将触发一个新的渲染,并且由于自上次调用useEffect以来更改计数器值时,它将运行useEffect回调。

答案 1 :(得分:0)

正如您提到的,ref.currentnull,直到组件安装完毕。您可以在此处使用useEffect-在安装组件后即会触发,即:

const useComponentIntoView = () => {
  const ref = useRef();
  useEffect(() => {
    if (ref.current) {
      window.scrollTo(0, ref.current.offsetTop );
    }
  });

  return ref;
}