React Hooks - Ref 在 useEffect 中不可用

RED*_*SAD 15 reactjs react-hooks

我正在使用 ReactHooks。我正在尝试访问功能中refUser组件useEffect。但是我得到了elRef.current价值null,虽然我elRef.current作为第二个参数传递给useEffect. 但我想得到对div元素的引用。但在 之外(函数体)useEffectref值是可用的。这是为什么 ?我怎样才能得到elRef.current里面的价值useEffect

代码

import React, { Component, useState, useRef, useEffect } from "react";

const useFetch = url => {
  const [data, setData] = useState(null);
  const [isLoading, setIsLoading] = useState(false);
  const [error, setError] = useState(null);

  useEffect(
    () => {
      setIsLoading(true);
      fetch(url)
        .then(response => {
          if (!response.ok) throw Error(response.statusText);
          return response.json();
        })
        .then(json => {
          setIsLoading(false);
          setData(json.data);
        })
        .catch(error => {
          setIsLoading(false);
          setError(error);
        });
    },
    [url]
  );

  return { data, isLoading, error };
};

const User = ({ id }) => {
  const elRef = useRef(null);
  const { data: user } = useFetch(`https://reqres.in/api/users/${id}`);

  useEffect(() => {
    console.log("ref", elRef.current);
  }, [elRef.current]);
  if (!user) return null;
  return <div ref={elRef}>{user.first_name + " " + user.last_name}</div>;
};

class App extends Component {
  state = {
    userId: 1
  };

  handleNextClick = () => {
    this.setState(prevState => ({
      userId: prevState.userId + 1
    }));
  };

  handlePrevNext = () => {
    this.setState(prevState => ({
      userId: prevState.userId - 1
    }));
  };
  render() {
    return (
      <div>
        <button
          onClick={() => this.handlePrevClick()}
          disabled={this.state.userId === 1}
        >
          Prevoius
        </button>
        <button onClick={() => this.handleNextClick()}>Next</button>
        <User id={this.state.userId} />
      </div>
    );
  }
}

export default App;
Run Code Online (Sandbox Code Playgroud)

代码沙盒链接

谢谢 !

liv*_*ine 31

您应该按照 reactjs文档中的建议使用useCallback而不是 useRef 。

每当 ref 附加到不同的节点时,React 都会调用该回调。

替换这个:

const elRef = useRef(null);
useEffect(() => {
    console.log("ref", elRef.current);
}, [elRef.current]);
Run Code Online (Sandbox Code Playgroud)

有了这个:

const elRef = useCallback(node => {
    if (node !== null) {
        console.log("ref", node); // node = elRef.current
    }
}, []);
Run Code Online (Sandbox Code Playgroud)

  • 这个应该选为最佳答案! (2认同)

z0r*_*z0r 10

当您使用函数作为 ref时,会在实例准备好时调用该函数。因此,使 ref 可观察的最简单方法是使用useState而不是useRef

const [element, setElement] = useState<Element | null>(null);
return <div ref={setElement}></div>;
Run Code Online (Sandbox Code Playgroud)

然后您可以在其他钩子的依赖数组中使用它,就像任何其他值一样const

useEffect(() => {
  if (element) console.log(element);
}, [element]);
Run Code Online (Sandbox Code Playgroud)

另请参阅如何在引用更改时重新渲染

  • 该方法相对于“useCallback”的优点是可以操作元素。例如,`element.scrollTop = number` 在这里可以工作,但它不适用于 `useCallback`。 (2认同)

Den*_*sur 5

这是一种可预测的行为。

如前所述,@estus您面临这个问题是因为第一次调用它时,componentDidMount您正在获取null(初始值)并且 get 仅在下次elRef更改时更新一次,因为实际上,引用仍然相同。

如果您需要反思每个用户更改,您应该将[user]第二个参数传递给 function 以确保useEffect在用户更改时触发。

是更新的沙箱。

希望它有所帮助。