【问题标题】:React Hooks, updated value of setState shows initial values in another componentReact Hooks,setState 的更新值在另一个组件中显示初始值
【发布时间】:2019-11-29 11:31:11
【问题描述】:

刚刚开始探索 React Hooks。我想创建一个 API 获取组件,将其导入另一个组件 - 这样我就可以在其他组件中重用 API 获取组件。

发生的事情是我设置了初始状态值:

Api.js

import { useState, useEffect } from "react";

export const useUserFetch = () => {

  const [users, setUsers] = useState({
    loading: true,
    error: false,
    data: [],
  });

然后在 useEffect 中进行异步获取:

useEffect(() => {
    async function fetchUserQuery() {
      await fetch('http://jsonplaceholder.typicode.com/users')
        .then(response => {
          console.log('API RESPONSE: ', response)
          if (response.status === 200 && response.status < 400) {
            response.json().then((respData) => {
              setUsers({ loading: false, error: false, data: respData })
            })
          } else {
            response.json().then(err => {
              setUsers({ loading: false, error: err, data: [] })
            })
          }
        }).catch(err => {
          setUsers({ loading: false, error: err, data: [] })
        })
    }
    fetchUserQuery()
  }, [])

如果响应状态为 200(ish),则更改我的状态数组以包含响应的更新值。错误处理也是如此。获取完成后,我检查并返回加载、错误和数据的值(以及控制台记录值):

if (users.loading) {
    console.log('API LOADING: ', users.loading)
    return "Loading..."
  }

  if (users.error) {
    console.log('API ERROR: ', users.error)
    return "Error..."
  }

  if (users.data) {
    console.log('API DATA: ', users.data)
    return users;
  }

如您所见,最后检查的是数据,如果有数据,控制台记录 API DATA 并返回数据。问题是,在数据返回之前的数据控制台输出显示用户数组(它有效,请参阅下面的包含控制台日志)。但是,当我将 Api.js 导入到我的 Contacts.js 并尝试输出数据时,它仍然显示用户状态的初始值。

Contacts.js:

import { useEffect, useState } from 'react'

import { useUserFetch } from '../Api';

const Users = () => {
    const [userData, setUserData] = useState(useUserFetch());
    console.log('CONTACT STATE: ', userData)

    useEffect(() => {
        async function fetchUserState() {
            const userJsonData = await userData
            setUserData(userJsonData)
        }
        fetchUserState()
    }, [])

    if (userData.loading) return "Loading...";
    if (userData.error) return userData.error.message
    if (userData.data) return JSON.stringify(userData.data)

    return true
};

export default Users

以下是控制台显示的内容(按确切顺序):

API 加载:真

Contacts.js:7 联系状态:加载中...

Api.js:14 API 响应:响应 {type: "cors", url: “http://jsonplaceholder.typicode.com/users”,重定向:假, 状态:200,确定:真,...}

Api.js:42 API 数据:(10) [{…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}]

Contacts.js:7 联系状态:加载中...

所以我的第一个问题;这是 setState 异步的问题吗?如果是这样,我该如何处理以确保当我返回我的用户状态时,我的 Contacts.js 获得更新的值。或者它是我的 useEffect 在任一文件中的异步?或者是其他东西?我只是想了解一下新的 Hooks,将来会探索 Redux/MobX 或 Context API。

【问题讨论】:

    标签: reactjs


    【解决方案1】:

    根据docs

    自定义 Hook 如何获得隔离状态? 对 Hook 的每次调用都会获得隔离状态。因为我们直接调用 [custome hook](修饰词,在文档中它是来自 example 的 hook 名称),从 React 的角度来看,我们的组件只是调用了 useState 和 useEffect。

    正如我们已经知道的,我们可以在一个组件中多次调用useState和useEffect,它们将是完全独立的。

    由于状态是隔离的,你必须有一个对你的自定义钩子的单独引用,将它作为第二个参数传递给useEffect,这样你就可以正确地获得一个状态,

    const App = () => {
        const [userData, setUserData] = useState(useUserFetch());
        let users = useUserFetch(); //Get seperate reference
    
        console.log('CONTACT STATE: ', userData)
    
        useEffect(() => {
            async function fetchUserState() {
                const userJsonData = await users //get data
                setUserData(userJsonData)
            }
            fetchUserState()
        },[users]) //Pass as dependency
    
        if (userData.loading) return "Loading...";
        if (userData.error) return userData.error.message
        if (userData.data) return JSON.stringify(userData.data)
    
        return true
    };
    
    

    【讨论】:

    • 是的,那是缺失的部分。感谢您对文档的参考和回答!
    猜你喜欢
    • 1970-01-01
    • 2021-09-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-23
    相关资源
    最近更新 更多