【问题标题】:Working of `useState` function inside `useEffect` function`useEffect` 函数中 `useState` 函数的工作
【发布时间】:2019-08-16 08:16:38
【问题描述】:

我正在尝试在useEffect 中使用useState。我想访问和修改其中的一个状态(useEffect),这里命名为isAuth,并根据新状态渲染组件。

import React, { useState, useEffect } from 'react';

const Authentication = () => {
    const [isAuth, setIsAuth] = useState(false);

    useEffect(() => {
        console.log(isAuth);
        setIsAuth(true);
        console.log(isAuth);
    }, [isAuth]);
    return <div>{isAuth ? <p>True</p> : <p>False</p>}</div>;
};

export default Authentication;

问题是在控制台中,我收到了falsefalsetruetrue。而不是这个控制台,我希望第二个控制台消息是真的。有人可以解释它是如何发生的,以及在组件渲染之前我如何实际更改状态?

【问题讨论】:

    标签: javascript reactjs react-hooks


    【解决方案1】:

    setIsAuth 不会导致局部变量isAuth 改变其值。 const 数据值无法更改,即使您将其定义为 let,这也不是设置状态的作用。相反,当您设置状态时,组件会重新呈现。在该新渲染上,对useState 的调用将返回新值,您可以使用该新值进行新渲染。

    组件第一次渲染。然后它运行效果。效果的闭包具有来自第一次渲染的局部变量,并且您的代码使用这些变量来记录两次错误。由于您调用了设置状态,因此会发生新的渲染,并且新的渲染将具有不同的变量。当它的效果运行时,它会记录两次 true,因为那是它的闭包中的值。

    【讨论】:

    • “效果总是从定义它们的渲染中“看到”道具和状态。”因此每个渲染都有自己的道具和状态。我建议阅读此内容以获取更多信息:overreacted.io/a-complete-guide-to-useeffect
    • 好的,我想说的是组件第一次渲染没有执行setState函数。对吗?
    • 组件第一次渲染。然后它运行效果。效果的闭包具有来自第一次渲染的局部变量,并且您的代码使用这些变量来记录两次错误。由于您调用了设置状态,因此将发生新的渲染,并且新的渲染将具有不同的变量。当它的效果运行时,它会记录两次 true,因为那是它的闭包中的值。
    • 谢谢 :) 的解释,我明白了你想要表达的意思,但你能告诉我有什么方法可以在第一次渲染之前更改我的默认状态。
    • 好吧,您可以将不同的值传递给 useState。你是这个意思吗?如果这需要一些同步计算,那么只需在调用 useState 之前在组件的主体中进行。如果它需要异步计算,那么你不能这样做,而不是使用单个组件。您可以拥有一个包装器组件,尽管它可以完成异步工作,并且只有在完成该工作后,它才会呈现一个子组件并将其传递给一个道具。由于在该道具可用之前永远不会渲染孩子,因此孩子将在第一次渲染时拥有它。
    【解决方案2】:

    代码中的一些 cmets 解释了 React setState 如何仅在组件重新渲染后更新本地常量

    import React, { useState, useEffect } from 'react';
    
    const Authentication = () => {
        // React will initialise `isAuth` as false
        const [isAuth, setIsAuth] = useState(false);
    
        useEffect(() => {
            // Console log outputs the initial value, `false`
            console.log(isAuth);
            // React sets state to true, but the new state is not available until
            // `useState` is called on the next render
            setIsAuth(true);
    
            // `isAuth` will remain false until the component re-renders
            // So console.log will output `false` again the first time this is called
            console.log(isAuth);
        }, [isAuth]);
    
        // The first time this is rendered it will output <p>False</p>
    
        // There will be a re-render after the `setState` call and it will
        // output <p>True</p> 
        return <div>{isAuth ? <p>True</p> : <p>False</p>}</div>;
    };
    
    export default Authentication;
    

    【讨论】:

      【解决方案3】:

      这实际上是正确的。 useEffect 可让您在更新后访问最新状态。所以在第一次渲染时,你看到的基本上是初始状态,不管你是否更新它。

      useEffect 内调用setState 将导致使用新状态(isAuth = true) 重新渲染,这将导致再次调用useEffect。此时,新记录的状态为真。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-10-16
        • 2021-12-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-12-03
        • 1970-01-01
        相关资源
        最近更新 更多