【问题标题】:why state always be 0, even after using useCallback为什么状态总是为 0,即使在使用 useCallback 之后
【发布时间】:2019-05-05 11:55:07
【问题描述】:

我希望它应该是一个计时器。 useCallback 会在时间改变后刷新,所以第二次时间为1, 但仍然是 0

我尝试使用 useCallback 但没有用

import React, { useState, useEffect, useCallback } from 'react';
import { render } from 'react-dom';
import './style.css';

import {interval} from 'rxjs'
import { take } from 'rxjs/operators';

const inter$ = interval(1000);

function App(){
  const [time, setTime] = useState(0);
  const callback = useCallback(()=> {
      setTime(time+1);
      console.log('hella');
    }, [time])

  useEffect(()=>{
    console.log('hello')
    inter$.subscribe(callback)

  }, [])

  return <div>{time}</div>
}


render(<App />, document.getElementById('root'));

总是显示 1

这是code

【问题讨论】:

    标签: javascript reactjs react-hooks


    【解决方案1】:

    useEffect 内部,回调不会改变,因为它不是依赖项。因此,订阅回调中的时间始终为 0。

    Rx.js:
    setTime 调用的工作解决方案基于回调函数内部的 prevState。

    import React, { useState, useEffect } from "react";
    import { render } from "react-dom";
    import "./style.css";
    
    import { interval } from "rxjs";
    import { take } from "rxjs/operators";
    
    const inter$ = interval(1000);
    
    function App() {
      const [time, setTime] = useState(0);
    
      useEffect(() => {
        console.log("hello");
        inter$.subscribe(() => {
          setTime(prevTime => prevTime + 1);
          console.log("hella");
        });
      }, []);
    
      return <div>{time}</div>;
    }
    
    render(<App />, document.getElementById("root"));
    

    【讨论】:

    • 另一种解释是 time 始终为 0,因为在订阅 inter$ 的当前上下文中,变量 time 的值为 0,并且永远不会更新。
    • @Rallen 但我使用了 useCallback ,它会由于依赖关系的变化而更新回调
    • 随便吧,可能是我误会官方文档了
    • 以下example 表明回调中的time 变量的值仍然为0。
    【解决方案2】:

    改变setTime(time+1);设置时间(时间=>时间+1); 这是完整的代码:

    import React, { useState, useEffect, useCallback } from 'react';
    import { render } from 'react-dom';
    import './style.css';
    
    import {interval} from 'rxjs'
    import { take } from 'rxjs/operators';
    
    const inter$ = interval(1000);
    
    function App(){
      const [time, setTime] = useState(0);
      const callback = useCallback(()=> {
          setTime(time=>time+1);
          console.log('hella');
        }, [time])
    
      useEffect(()=>{
        console.log('hello')
        inter$.subscribe(callback)
    
      }, [])
    
      return <div>{time}</div>
    }
    
    
    
    render(<App />, document.getElementById('root'));
    

    stackblitz

    【讨论】:

    • 为什么useCallback没有更新回调里面的时间
    • 传递一个内联回调和一个依赖数组。 useCallback 将返回回调的记忆版本,仅当其中一个依赖项发生更改时才会更改。这在将回调传递给优化的子组件时很有用,这些子组件依赖于引用相等来防止不必要的渲染(例如 shouldComponentUpdate)。它应该像我期望的那样更新回调内部的时间
    • 依赖项应该如何改变必须写在'setState'(在你的情况下是setTIme)方法中。所以基本上 setTIme 接收时间作为参数并更新时间增加 1
    • useEffect 的第二个参数应该是[callback] - 另见react-hooks/exhaustive-deps eslint 规则
    猜你喜欢
    • 1970-01-01
    • 2019-02-02
    • 2012-07-14
    • 1970-01-01
    • 2020-07-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多