useRef() 比 ref 属性更有用。它可以很方便地保存任何可变值

只在更新时运行 effect

这是个比较罕见的使用场景。如果你需要的话,你可以 使用一个可变的 ref 手动存储一个布尔值来表示是首次渲染还是后续渲染,然后在你的 effect 中检查这个标识。(如果你发现自己经常在这么做,你可以为之创建一个自定义 Hook。)

function Example () {
  const [count, setCount] = useState(0);

  const prevCountRef = useRef(false);
  useEffect(() => {
    if (prevCountRef.current) {
      console.log('只在更新时候执行')
    } else {
      prevCountRef.current = true
    }
  });

  return (
    <div>
      <div>{count}</div>
      <button onClick={() => {setCount(count+1)}}>+</button>
    </div>
  )
}

这或许有一点错综复杂,但你可以把它抽取成一个自定义 Hook:

function Example () {
  const [count, setCount] = useState(0);

  const update = useUpdate()
  console.log(update, '是否更新')

  return (
    <div>
      <div>{count}</div>
      <button onClick={() => {setCount(count+1)}}>+</button>
    </div>
  )
}

function useUpdate () {
  const ref = useRef(false)
  useEffect(() => {
    ref.current = true
  })
  return ref.current
}

获取上一轮的 props 或 state

目前,你可以 通过 ref 来手动实现:

function Example () {
  const [count, setCount] = useState(0);

  const prevCountRef = useRef();
  useEffect(() => {
    prevCountRef.current = count
  });

  const prevCount = prevCountRef.current
  console.log(prevCount, count, '之前的状态和现在的状态')
  return (
    <div>
      <div>{count}</div>
      <button onClick={() => {setCount(count+1)}}>+</button>
    </div>
  )
}

这或许有一点错综复杂,但你可以把它抽取成一个自定义 Hook:

function Example () {
  const [count, setCount] = useState(0);

  const prevCount = usePrevious(count)
  console.log(prevCount, count, '之前的状态和现在的状态')
  return (
    <div>
      <div>{count}</div>
      <button onClick={() => {setCount(count+1)}}>+</button>
    </div>
  )
}
function usePrevious (value) {
  const ref = useRef()
  useEffect(() => {
    ref.current = value
  })
  return ref.current
}

函数中看到陈旧的 props 和 state

组件内部的任何函数,包括事件处理函数和 effect,都是从它被创建的那次渲染中被「看到」的。

function Example () {
  const [count, setCount] = useState(0);

  function handleAlertClick () {
    setTimeout(() => {
      console.log(count)
    }, 3000)
  }

  function increment () {
    let newCount = count + 1;
    setCount(newCount)
  }

  return (
    <div>
      <div>{count}</div>
      <button onClick={increment}>+</button>
      <button onClick={handleAlertClick}>点击</button>
    </div>
  )
}

如果你刻意地想要从某些异步回调中读取 最新的 state,你可以用 一个 ref 来保存它,修改它,并从中读取。

function Example () {
  const [count, setCount] = useState(0);
  const ref = useRef(0)

  function handleAlertClick () {
    setTimeout(() => {
      console.log(ref.current)
    }, 3000)
  }

  function increment () {
    let newCount = count + 1;
    setCount(newCount)
    ref.current = newCount
  }

  return (
    <div>
      <div>{count}</div>
      <button onClick={increment}>+</button>
      <button onClick={handleAlertClick}>点击</button>
    </div>
  )
}

请记住,当 ref 对象内容发生变化时,useRef 并不会通知你。变更 .current 属性不会引发组件重新渲染。如果想要在 React 绑定或解绑 DOM 节点的 ref 时运行某些代码,则需要使用回调 ref 来实现。

已标记关键词 清除标记
相关推荐
©️2020 CSDN 皮肤主题: 技术工厂 设计师:CSDN官方博客 返回首页