为什么使用 React Hooks、MomentJS 对象和间隔/超时更新状态不会触发重新渲染?

Hon*_*loň 1 javascript reactjs react-native react-hooks

我正在尝试使用 React-Native、React Hooks、MomentJS 和 (setTimeout/setInterval) 制作一个倒计时器。无论我尝试使用什么方法,它都会失败。问题是组件永远不会重新渲染。

我尝试遵循官方 React Hooks 文档、Medium 上的几篇文章,例如The Iceberg of React Hooks,但没有任何效果。

一种可能性是它需要 MomentJS 对象的深度克隆,但我认为这是一种低效的方法。

这是我尝试过的可重现的示例之一。

const Timer = () => {
  const [time, setTime] = useState(moment.duration(30, 'seconds'))
  const intervalRef = useRef()

  useEffect(() => {
    intervalRef.current = setTimeout(() => {
      setTime(prevTime => prevTime.subtract(1, 'second'))
    }, 1000)

    return () => {
      clearInterval(intervalRef.current)
      intervalRef.current = null
    }
  })

  return (
    <View>
      {time.asSeconds()}
    </View>
  )
Run Code Online (Sandbox Code Playgroud)

Wil*_*ins 6

你是对的,它不会重新渲染,因为你的时刻对象在每次更新时都是相同的(但发生了变化)。.clone()您可以通过添加更新程序轻松使其工作setTime

const Timer = () => {
  const [time, setTime] = useState(moment.duration(30, "seconds"));
  const intervalRef = useRef();

  useEffect(() => {
    intervalRef.current = setTimeout(() => {
      setTime(prevTime => prevTime.clone().subtract(1, 'second'))
    }, 1000)

    return () => {
      clearInterval(intervalRef.current)
      intervalRef.current = null
    }
  })

  return <div>{time.asSeconds()}</div>;
};
Run Code Online (Sandbox Code Playgroud)

此处工作沙箱:https://codesandbox.io/s/gifted-euler-e8xg5