【问题标题】:How do I get updated state immediately when using setState?使用 setState 时如何立即获取更新状态?
【发布时间】:2020-08-26 13:42:21
【问题描述】:

我有一个 ViewColumn 组件。我使用registerColumn 方法将列refs 存储在View 上下文中:

const [columns, setColumns] = useState([]);

const registerColumn = (node) => {
    const column = {
        someUniqueId: Math.random(),
        node,
        // more props
    };

    setColumns(prev => [...prev, column])
}

const context = {
    columns,
    registerColumn
}

<ViewContext.Provider values={context}>
    <View>
        <Column/>
        <Column/>
        <Column/>
    </View>
    <View>
        <Table/>
    </View>
</ViewContext.Provider>

我真正感到困惑的是Column 组件。每当我尝试注册该列并在之后获取更新的长度时,它都不会按时更新,因为setState 异步工作:

const {columns, registerColumn} = useContext(ViewContext);
const ref = useRef(null);

useEffect(() => {
    registerColumn(ref.current);

    // Here is where updated column length but it keeps saying it's 0 length
    console.log(`Hello from column number ${columns.length}`);
}, []);

[...]

文档说,我可以使用 useEffectcolumns 作为依赖项,并在下次渲染时更新长度。但是,我需要在调用 registerColumn 后立即使用更新的状态 - 使用 another useEffect 基本上意味着破坏执行上下文和需要延迟任务,加上可能引入其他回调只是为了得到围绕这个。

我是 React 的新手,但我很确定还有其他方法可以解决这个问题,因此我们将不胜感激。

【问题讨论】:

    标签: javascript reactjs react-hooks state react-context


    【解决方案1】:

    更新 useEffect 中的 setState 和 useEffect 中的控制台日志将不起作用,因为 useState 异步工作,并且对所有状态做出反应并更新一次。它正在更新状态,但它不会反映那个时刻,因为会通过更新对批次做出反应。
    您可以使用其他具有列依赖的 useEffect,因此每次 registerColumn 更新时,都会调用第二个 useEffect 并控制台记录该值。

    useEffect(() => {
        registerColumn(ref.current);
    }, []);
    
    
    useEffect(() => {
        console.log(`Hello from column number ${columns.length}`);
    },[columns]);
    
    

    【讨论】:

    • 问题是,正如您在我发布的 JSX 中看到的那样,那里有 3 列。安装后,这一切都发生得太快了,控制台消息会说同样的消息 3 次:Hello from column number 3 ignoring 1 和 2 :(
    • 我看到很多次提到异步,但问题不是因为异步方法,你只是在记录一个stale closure。异步的 Setstate 在类组件中。
    • @HMR 我不相信这是真的。事实是useEffect 缺少columns 的依赖项,但是引入一个并没有改变,因为useState still works asynchronously
    猜你喜欢
    • 2018-08-05
    • 2021-08-30
    • 1970-01-01
    • 2018-08-12
    • 2019-11-15
    • 1970-01-01
    • 2021-08-18
    相关资源
    最近更新 更多