如何使用useRef引用最新值

时间:2020-02-14 07:38:12

标签: reactjs react-hooks

人们使用useRef来保存最新的值,例如此代码

function MyComponent({ value }) {
  const valueRef = useRef();
  useEffect(() => {
    valueRef.current = value;
  });
}

我知道并发模式需要useEffect。

和useEffect按照定义的顺序执行

function MyComponent({ value }) {
  useEffect(() => {
    console.log('log1');
  });
  useEffect(() => {
    console.log('log2');
  });
}
// result is
// log1
// log2

所以在下面的代码中, log1打印旧值,log2打印新值

function MyComponent({ value }) {
  const valueRef = useRef();
  useEffect(() => {
    console.log('log1', valueRef.current);
  });
  useEffect(() => {
    valueRef.current = value;
  });
  useEffect(() => {
    console.log('log2', valueRef.current);
  });
}

我认为这很奇怪,因为根据位置的不同,值也不同。

使用useRef引用最新值的正确方法是什么? (仅供参考,我知道使用deps比使用useRef更好)

4 个答案:

答案 0 :(得分:1)

这实际上取决于您所说的最新值,您的代码会将最新值存储到valueRef.current中。

  const valueRef = useRef();
  useEffect(() => {
    console.log('log1', valueRef.current);
  });
  useEffect(() => {
    valueRef.current = value;
  });
  useEffect(() => {
    console.log('log2', valueRef.current);
  });

如果您确实希望获得更“稳定”的值,则应使用setState

  const valueRef = useRef();
  const [value, setValue] = useState(null);

  useEffect(() => {
    setValue(1)
    console.log('log1', valueRef.current);
  });
  useEffect(() => {
    // value is still 1
    valueRef.current = value;
  });
  useEffect(() => {
    // value is still 1
    console.log('log2', valueRef.current);
  });

恕我直言,useRef是一个非常困难的话题,最初是为Dom ref设计的。但是随后,人们发现将变量与渲染状态/ prop分离时很有用。您实际上不能说useRef总是存储最新的值,它实际上仍然存储常规值,除非它不会触发重新渲染,因为对此ref的引用在初始化后是固定的(只有ref.current正在更改)。

答案 1 :(得分:0)

要从所有代码位置(渲染,useEffect主体,处置函数主体)获取最新值,您必须至少使用两个useRef

这是代码

export const usePrevRef = value => {
    const currentRef = useRef()
    const prevPref = useRef()
    prevPref.current = currentRef.current
    currentRef.current = value
    return prevPref
}

enter image description here

如果您使用一个useRef,并将ref.current = value更新放在③(或⑤)中,则从④和⑥(或⑥)调用该值将不正确。

我为此写了blog。请随时检查。

答案 2 :(得分:0)

另一种方法是在if条件之后更改参考值。

  const valueRef = useRef();
  useEffect(() => {
    console.log('log1', valueRef.current);
  });
  if(valueRef.current !== value) {
    valueRef.current = value;
  };
  useEffect(() => {
    console.log('log2', valueRef.current);
  });

答案 3 :(得分:-1)

惯用的方法是为下一个渲染存储 some “当前”值,并检索当前的ref值(前一个值)。 Hooks FAQ: How to get the previous props or state

const prevValueRef = useRef();
useEffect(() => {
  prevValueRef.current = value; // cache current value for next render
});
const prevValue = prevValueRef.current; // get previous value from last render

正在运行的沙箱演示

Edit useRef-previous-value