useRef 简单易懂解析(二)useRef 的例子

2,021 阅读2分钟

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。

翻译自:beta.reactjs.org/learn/refer…

当你希望组件“记住”一些信息,但是你不希望这些信息触发重新 render 的时候,你可以使用 ref,它像一个秘密的“口袋”,用于在组件中存储信息。

系列文章

useRef 简单易懂解析(一)useRef 的使用

useRef 简单易懂解析(二)useRef 的例子

示例:构建秒表

你可以在单个组件中结合使用 refs 和 state。例如,让我们制作一个秒表,用户可以通过按按钮来启动或停止它。为了显示从用户按下 “Start” 以来已经过去了多长时间,你需要跟踪按下 “Start” 按钮的时间以及当前时间。这些信息是用于渲染的,所以你可以把它保存在 state 里面:

const [startTime, setStartTime] = useState(null);
const [now, setNow] = useState(null);

当用户按下 “Start” 时,你将使用 setInterval 每 10 毫秒更新一次时间,就像下面的例子:

import { useState } from 'react';

export default function Stopwatch() {
  const [startTime, setStartTime] = useState(null);
  const [now, setNow] = useState(null);

  function handleStart() {
    // 开始计时
    setStartTime(Date.now());
    setNow(Date.now());

    setInterval(() => {
      // 每 10ms 更新一次时间
      setNow(Date.now());
    }, 10);
  }

  let secondsPassed = 0;
  if (startTime != null && now != null) {
    secondsPassed = (now - startTime) / 1000;
  }

  return (
    <>
      <h1>Time passed: {secondsPassed.toFixed(3)}</h1>
      <button onClick={handleStart}>
        Start
      </button>
    </>
  );
}

当按下 “Stop” 按钮时,你需要取消现有的 interval,用来停止更新 now 这个 state。你可以调用 clearInterval 来实现,但是你需要给它一个 interval ID,这个 ID 以前是在用户按下 Start 时由 setInterval 调用返回的。你需要把 interval ID 保存在某个地方。由于 interval ID 不用于渲染,你可以将它保存在ref中:

import { useState, useRef } from 'react';

export default function Stopwatch() {
  const [startTime, setStartTime] = useState(null);
  const [now, setNow] = useState(null);
  const intervalRef = useRef(null);

  function handleStart() {
    setStartTime(Date.now());
    setNow(Date.now());
    intervalRef.current = setInterval(() => {
      setNow(Date.now());
    }, 10);
  }

  function handleStop() {
    clearInterval(intervalRef.current);
  }

  let secondsPassed = 0;
  if (startTime != null && now != null) {
    secondsPassed = (now - startTime) / 1000;
  }

  return (
    <>
      <h1>Time passed: {secondsPassed.toFixed(3)}</h1>
      <button onClick={handleStart}>
        Start
      </button>
      <button onClick={handleStop}>
        Stop
      </button>
    </>
  );
}

当一个信息用于渲染时,把它保存在 state 中。当一个信息只被事件处理程序需要,并且改变它不需要 re-render 时,使用 ref 可能更有效。