Javascript - 来自异步获取的 React Data 未使用 'useEffect()' 和 'useState' 定义



我很新反应。我试图从API获取一些数据。我想取回一个用户。但是,当我稍后要处理用户数据时,用户是未定义的。我对async函数是如何工作的感到困惑。

我想获取一个用户,然后将该用户传递给UserInfo组件。在UserInfo组件中,我想在将数据显示在网站上之前对其进行处理。我收到一个错误:TypeError: Cannot read property 'split of undefined".

任何帮助都是非常感激的!

App.js

function App() {
const classes = useStyles()
const [user, setUser] = useState({})
const [posts, setPosts] = useState([])
const [userList, setUserList] = useState([])
useEffect(() => {
const getUser = async () => {
const userFromServer = await fetchUser()
if (userFromServer) {
setUser(userFromServer)
} else {
console.log("error")
}
}
const getPosts = async () => {
const postsFromServer = await fetchPosts()
setPosts(postsFromServer)
}
const getUserList = async () => {
const userListFromServer = await fetchUserList()
setUserList(userListFromServer)
}
getUser()
getPosts()
getUserList()
}, [])
// Fetch user 
const fetchUser = async () => {
const res = await fetch('https://jsonplaceholder.typicode.com/users/1')
const data = await res.json()
return data
}
// Fetch posts
const fetchPosts = async () => {
const res = await fetch('https://jsonplaceholder.typicode.com/posts?userId=1')
const data = await res.json()
return data
}
// Fetch list of users
const fetchUserList = async () => {
const res = await fetch('https://jsonplaceholder.typicode.com/users/')
const data = await res.json()
return data
}
return (
<div>
<Box className={classes.headerImage}>
<UserMenu userList = {userList} />
</Box>
<Container maxWidth="lg" className={classes.userContainer}>
<UserInfo user = {user} />
</Container>
<Container maxWidth="lg" className={classes.blogsContainer}>
<PostList name = {user.name} posts = {posts} />
</Container>
</div>
);
} 
export default App;

UserInfo.js

const classes = useStyles()
console.log(user.phone)
const phoneStr = user.phone.split(" ")[0]
// var companyStr = user.company.bs.replaceAll(" ", "· ")
// const addressDic = user.address
// const addressStr = addressDic.street + " " + addressDic.suite + " " + addressDic.city + " " +addressDic.zipcode
return (
<div>
<h2>{user.name}</h2>
<Paper elevation={0} className={classes.paper}>
<Grid container>
<Grid item xs={1}>
<img className={classes.icon} src={phoneIcon} />
</Grid>
<Grid item className={classes.gridText} xs={11}>
{phoneStr}
</Grid>
<Grid xs={1}>
<img className={classes.icon} src={categoryIcon} />
</Grid>
<Grid item className={classes.gridText} xs={11}>

</Grid>
<Grid item xs={1}>
<img className={classes.icon} src={shopIcon} />    
</Grid>
<Grid item className={classes.gridText} xs={11}>

</Grid>
</Grid>
</Paper>
</div>
)
}
export default UserInfo

这是因为用户信息并不总是可用的。在等待获取用户数据时,组件树继续呈现。user.phone将未定义,undefined.split()将导致错误。

可以先检查user是否存在来解决这个问题。

user.phone && user.phone.split(" ")[0]

但是,这只能解决一行问题,您需要对User组件中的每次查找都这样做,这不是很好。最好将user的默认状态设置为null。

const [user, setUser] = useState(null)

然后只在User不为空时呈现User组件

<Container maxWidth="lg" className={classes.userContainer}>
{ user ? <UserInfo user = {user} /> : 'loading...'} 
</Container>

首先,在Promise.all中获取调用,这样您就可以确保在设置状态之前正确执行所有调用,在useEffect:

useEffect(() => {
const getUser = async () => await fetchUser();
const getPosts = async () => await fetchPosts();
const getUserList = async () => await fetchUserList();
(async () => {
try {
const [response1, response2, response3] = await Promise.all(getUser(), getPosts(), getUserList());
userFromServer && setUser(response1);
setPosts(response2);
setUserList(response3);
} catch (err) {
throw new Error(`Something went wrong: ${err}`);
}
})();
}, []);

然后,在返回中等待,直到用户数据设置完毕,如:

{user?.phone && <UserInfo user={user} />}

最新更新