React Context 在获取用户数据时创建了一个无限循环

Posted

技术标签:

【中文标题】React Context 在获取用户数据时创建了一个无限循环【英文标题】:React Context is creating an infinite loop when fetching user data 【发布时间】:2022-01-05 09:36:59 【问题描述】:

我有一个 React 上下文,所以我可以保存一些数据并在我的 React-Project 中重用它。这是我正在处理的代码:

import React,  useState, createContext  from "react"
import apiRequest from "../axios"
import  getCookie  from "../Utils"
import jwt_decode from "jwt-decode"

export const UserContext = React.createContext()

export const UserProvider = (props) => 
    const [value, setValue] = useState(
        loading: false,
        isLoggedIn: false,
        userId: "",
        username: ""
    )

    const updateData = (toUpdate) => 
        setValue(...value, ...toUpdate)
    

    const fetchUser = async (userId, key) => 
        await apiRequest("get", "/user/" + userId, null, () => , (data) => 
            updateData(
                loading: false,
                isLoggedIn: true,
                userId: userId,
                username: data.user.username
            )

        , (errMessage) => 

            updateData(
                loading: false
            )

        , key)
    

    // load user data if access token is set
    const accessToken = getCookie("access")
    if (accessToken && !value.loggedIn && !value.loading) 
        updateData( loading: true )
        const  sub: userId  = jwt_decode(accessToken)
        fetchUser(userId, accessToken)              // if I comment this out, then no infinite loop
    

    const methods = 
        fetchUser,
        updateData
    

    return (
        <UserContext.Provider value=[value, methods]>
            props.children
        </UserContext.Provider>
    )

我已经评论了创建此循环的行。谁能告诉我为什么会这样?

【问题讨论】:

【参考方案1】:

您需要在 useEffect 中执行 fetch 请求,以便仅在安装组件或 cookie 值更改时触发它。

试试这个;

import React,  useState, createContext, useEffect  from "react"
import apiRequest from "../axios"
import  getCookie  from "../Utils"
import jwt_decode from "jwt-decode"

export const UserContext = React.createContext()

export const UserProvider = (props) => 
    const [value, setValue] = useState(
        loading: false,
        isLoggedIn: false,
        userId: "",
        username: ""
    )

    const updateData = (toUpdate) => 
        setValue(...value, ...toUpdate)
    

    const fetchUser = async (userId, key) => 
        updateValue( loading: true );
        await apiRequest("get", "/user/" + userId, null, () => , (data) => 
            updateData(
                loading: false,
                isLoggedIn: true,
                userId: userId,
                username: data.user.username
            )

        , (errMessage) => 
            updateData(loading: false)
        , key)
    

    // load user data if access token is set
    const accessToken = getCookie("access")
    useEffect(() => 
      if (accessToken && !value.loggedIn && !value.loading) 
        const  sub: userId  = jwt_decode(accessToken)
        fetchUser(userId, accessToken);
      
    , [accessToken, value.loggedId, value.loading]);

    const methods = 
        fetchUser,
        updateData
    

    return (
        <UserContext.Provider value=[value, methods]>
            props.children
        </UserContext.Provider>
    )

【讨论】:

哇,我仍然不知道为什么,但它有效哈哈。但是 fetchUser-Method 现在被调用了两次,为什么呢? 我已经更新了 useEffect [accessToken, value.loggedId, value.loading] 中的依赖关系。此外,fetchUser 会在组件挂载时调用,因此在第一次渲染时使用上下文时不必调用它。

以上是关于React Context 在获取用户数据时创建了一个无限循环的主要内容,如果未能解决你的问题,请参考以下文章

如何获取数据并存储在 React Context API 中?

React使用context进行组件通信

React/React Context API:使用 useEffect() 钩子时等待上下文值

react

React的Context对象解决props传递数据的烦恼!

(React Context 初学者)使用 react-router-dom 更改页面时,React Context 不启动