刚刚开始探索 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(左右),则更改我的状态数组以包含响应的更新值。错误处理也一样。获取完成后,我检查并返回加载、错误和数据的值(以及控制台记录这些值):
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 LOADING: true
Contacts.js:7 CONTACT STATE: Loading...
Api.js:14 API RESPONSE: Response {type: "cors", url: "http://jsonplaceholder.typicode.com/users", redirected: false, status: 200, ok: true, …}
Api.js:42 API DATA: (10) [{…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}]
Contacts.js:7 CONTACT STATE: Loading...
所以我的第一个问题;这是 setState 异步的问题吗?如果是这样,我该如何处理这个问题以确保当我返回用户状态时,我的 Contacts.js 获得更新的值。或者它是任一文件中我的 useEffect 中的异步?或者是其他东西?我只是想了解一下新的 Hooks,并在将来探索 Redux/MobX 或 Context API。
最佳答案
根据docs ,
How does a custom Hook get isolated state? Each call to a Hook gets isolated state. Because we call [custome hook](modified word, in docs it is a hook name from example) directly, from React’s point of view our component just calls useState and useEffect.
正如我们所知,我们可以在一个组件中多次调用 useState 和 useEffect,并且它们将完全独立。
由于状态是隔离的,因此您必须对自定义 Hook 有一个单独的引用,将其作为第二个参数传递给 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
};
关于reactjs - React Hooks,setState 的更新值显示另一个组件中的初始值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57129934/