【问题标题】:state update from a callback来自回调的状态更新
【发布时间】:2022-01-20 10:47:34
【问题描述】:

以下成员函数使用假数据异步填充 folder_structure 对象:

    fake(folders_: number, progress_callback_: (progress_: number) => void = (progress_: number) => null): Promise<boolean>
    {
        return new Promise((resolve, reject) => {
            for (let i_ = 0; i_ < folders_; i_++) {
                progress_callback_(i_ / folders_ * 100.);

                this.add(this.id(), faker.address.city() + i_, random_choice(this.folder_structure_id()));
            }

            progress_callback_(folders_ / folders_ * 100.);

            resolve(true);
        })
    }

它使用回调来更新for 循环中的进度,然后使用该循环从具有空依赖数组的useEffect() 函数中更新状态(进度条)。

   let [progress_state_, set_progress_state_] = useState<number>(0);

   let [fake_done_, set_fake_done_] = useState<boolean>(false);

    useEffect(() =>
    {
        if (fake_)
            folder_structure_.fake(fake_, (progress_) => {
                set_progress_state_(progress_)
            }).then(value => set_fake_done_(value));
    }, [])

    if (!fake_ || fake_done_) etc etc

但是,状态没有更新(在控制台中记录进度似乎工作正常)。关于是否可以从 useEffect 中更新状态的任何想法?

【问题讨论】:

    标签: javascript reactjs typescript oop


    【解决方案1】:

    useEffect 钩子不起作用的原因是它没有在 progress_state_ 状态更改时调用。

    代替

    useEffect(() =>
        {
            ...
        }, [])
    

    试试这个

    useEffect(() =>
        {
            ...
        }, [progress_])
    

    progress_ 添加到依赖数组意味着useEffect 将在每次progress_ 更改时被调用。如果将其保留为空的依赖数组,那么 useEffect 只会在代码挂载到 DOM 的最开始时被调用。

    这里有一个关于依赖数组的很好的解释:https://devtrium.com/posts/dependency-arrays

    【讨论】:

    • 从回调内部更新状态,useEffect只需要调用一次,注册回调
    【解决方案2】:

    解决您的最后一个问题:是的,可以从useEffect 中更新状态。

    要了解您的主要问题的根源,我很想知道您是如何进行日志记录的。您是从 fake() 还是从您的 render() 函数登录?

    【讨论】:

    • console.log() 在用于更新状态的set_progress_state 正下方的回调中调用。似乎状态更新不足以重新渲染组件,如果我将一些裸日志代码放在应该在每次渲染时调用的函数中的任何位置,就会变得很明显。
    • 记录:`folder_structure_.fake(fake_, (progress_) => { set_progress_state_(progress_); console.log(progress_state_); console.log(progress_); `outputs: 0 for the通过回调的状态和正常进度
    • 你是说每个console.log()只输出一次0?还是因为回调函数会被多次调用而输出多个0s?
    • 当涉及到回调传递的进度时,它会输出正确的进度,但是当我记录状态时输出正确的进度,这意味着状态没有更新。有趣的是,如果我使用超时将 set_fake_done 延迟 1 秒,我确实会获得进度更新,这归因于在 React 中设置状态的异步性质。这也意味着要更新耗时任务的进度并不是很容易
    猜你喜欢
    • 1970-01-01
    • 2020-08-08
    • 1970-01-01
    • 2019-01-28
    • 1970-01-01
    • 1970-01-01
    • 2017-12-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多