我对 React 中的 setState 有疑问,特别是当它位于 fetch 的回调函数内以及何时不在时

问题描述 投票:0回答:2

为什么在第一个代码中,当调用 setAllMemes 时,组件会在重新渲染之前等待所有代码完成,而在第二个代码中,它会在代码完成之前重新渲染

第一个代码

import React from "react"

export default function Meme() {
    console.log("react render")
    const [allMemes, setAllMemes] = React.useState([])

    console.log("allMemes outside the use effect" , allMemes)    

    React.useEffect(() => {
    
        console.log("before setAllMemes")
        setAllMemes(["string1","string2"]);
        console.log("after setAllMemes");
            
        console.log("allMemes inside the use effect" , allMemes);
    }, [])

    return (
        <main>
        
        </main>
    )
}

控制台的输出

›react render
›allMemes outside the use effect,[]
›before setAllMemes
›after setAllMemes
›allMemes inside the use effect,[]
›react render
›allMemes outside the use effect,["string1", "string2"]

第二个代码

import React from "react"

export default function Meme() {
     console.log("react render")
     const [allMemes, setAllMemes] = React.useState([])

     console.log("allMemes outside the use effect" , allMemes)    

     React.useEffect(() => {
        fetch("https://api.imgflip.com/get_memes")
            .then(res => res.json())
            .then(data => {
                console.log("before setAllMemes")
                setAllMemes(data.data.memes);
                console.log("after setAllMemes");
                })
        console.log("allMemes inside the use effect" , allMemes);
        }, [])

        return (
            <main>
        
            </main>
        )
    }

控制台的输出

›react render
›allMemes outside the use effect,[]
›allMemes inside the use effect,[]
›before setAllMemes
›react render
›allMemes outside the use effect [array of object from the api]
›after setAllMemes
javascript reactjs
2个回答
0
投票

在第一个代码片段中,setAllMemes 函数在 useEffect 挂钩内同步调用。由于这是同步的,因此它会在执行下一行代码之前完成。当您在 useEffect 中记录 allMemes 时,它仍然显示一个空数组,因为状态更新尚未生效。当组件在状态更新后重新渲染时,会显示更新后的 allMemes 数组。

在第二个代码片段中,从 api 获取数据后,在 useEffect 挂钩内异步调用 setAllMemes 函数。 fetch 返回一个 Promise,并且在 Promise 的 then 回调中调用 setAllMemes 函数。这意味着setAllMemes是异步调用的,在获取数据的过程中,获取操作之后的下一行代码将继续执行。当您在 useEffect 中记录 allMemes 时,它仍然显示一个空数组,因为状态更新尚未发生。


0
投票

您的输出出现问题。通过运行此代码片段进行检查。

after setAllMemes
之前不渲染。

function Meme() {
     console.log("react render")
     const [allMemes, setAllMemes] = React.useState([])

     console.log("allMemes outside the use effect" , allMemes)    

     React.useEffect(() => {
        fetch("https://api.imgflip.com/get_memes")
            .then(res => res.json())
            .then(data => {
                console.log("before setAllMemes")
                setAllMemes(data.data.memes);
                console.log("after setAllMemes");
                })
        console.log("allMemes inside the use effect" , allMemes);
        }, [])

        return (
            <main>
        
            </main>
        )
    }
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(<Meme />);
<div id="root"></div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.1.0/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.1.0/umd/react-dom.development.js"></script>

© www.soinside.com 2019 - 2024. All rights reserved.