【问题标题】:Updating useState with server response JSON object使用服务器响应 JSON 对象更新 useState
【发布时间】:2020-12-26 01:11:13
【问题描述】:

我有一个钩子状态,我将其设置为一个空对象,并带有要启动的属性值。如果一个属性不存在,它不在初始化时,那么它调用一个 API,它将添加对象属性。在我尝试将响应对象从 API 传递到我的状态挂钩并收到错误之前,此过程运行良好。如果我将对象包装在另一个对象中(通过大括号),它可以工作,但将对象嵌套在属性 data 下。

是否有任何理由为什么钩子只接受将对象包装在对象中?我宁愿只使用从服务器接收到的数据对象。

这是setUser(data)的错误消息:

Error: Rendered fewer hooks than expected. This may be caused by an accidental early return statement.

这是反应代码:

import React, { createContext, useContext, useEffect, useState } from 'react'

import axios from 'axios'

export const SessionContext = createContext(null);

const AppSession = ({ children }) => {
    const [user, setUser] = useState({ authenticated: false, user_id: '', user_email: ''})

    if (user){
        if(user.session_present === undefined){
            console.log("Session is not present")
            useEffect(()=> {
            axios.get('/api/auth/session/')
                .then(res => {
                    console.log('/api/auth/session/ success')
                    const data = res.data;
                    console.log(typeof(data)) // Object
                    console.log(data) // { 'authenticated': true, 'user_id':'example', 'user_email:'example', 'session_present': true }
                    setUser(data) // Doesn't work. {data} works, but nests the object to {data: { 'authenticated': true, 'user_id':'example', 'user_email:'example', 'session_present': true }}
                })
                .catch(err => {
                    console.log(err)
                });
        }, [])
        } else {
            console.log("Session is present")
        }
    } else {
        console.log("useState: Not authenticated")
        console.log(user)
    }

    return (
        <SessionContext.Provider value={{user, setUser}}>
            {children}
        </SessionContext.Provider>
    )

}

export const getUserState = () => {
    const { user } = useContext(SessionContext)
    return user;
}

export const updateUserState = () => {
    const { setUser } = useContext(SessionContext)
    
    return (user) => {
        setUser(user);
    }
}

export default AppSession;

服务器代码:

router.route('/session/')
    .get((req, res) => {
        if(req.user){
            res.json({
                authorized: true,
                user_id: req.user.id,
                user_email: req.user.email,
                session_present: true
            });
        } else {
            res.json({
                authorized: false,
                user_id: '',
                user_email: ''
            })
        }
    })

【问题讨论】:

    标签: reactjs react-hooks react-state


    【解决方案1】:

    钩子不能被有条件地调用。每次给定组件渲染时,它必须以完全相同的顺序调用完全相同数量的钩子。所以你需要把目前在useEffect之外的那些ifs移到里面去。

    useEffect(() => {
      if (user) {
        if (user.session_present === undefined) {
          axios
            .get("/api/auth/session/")
            .then((res) => {
              console.log("/api/auth/session/ success");
              const data = res.data;
              setUser(data);
            })
            .catch((err) => {
              console.log(err);
            });
        } else {
          console.log("Session is present");
        }
      } else {
        console.log("useState: Not authenticated");
        console.log(user);
      }
    }, []);
    
    

    欲了解更多信息,请参阅Rules of Hooks


    当你用一个对象设置状态时你没有得到错误的原因是你把你的数据放在一个错误的格式中,所以user.session_present总是undefined。因为一直是undefined,所以useEffect总是被调用,所以遵守hook的规则。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-07-11
      • 2017-07-01
      • 2021-08-23
      • 2014-11-14
      • 1970-01-01
      • 2019-11-15
      • 1970-01-01
      相关资源
      最近更新 更多