如何等待 useEffect 中的 setState 直到渲染?
2022-03-06
3003
let [item, setItem] = useState({});
let [comments, setComments] = useState([]);
useEffect(async () => {
await axios
.all([
axios.get(`https://dummyapi.io/data/v1/post/${id}`, {
headers: { "app-id": process.env.REACT_APP_API_KEY }
}),
axios.get(`https://dummyapi.io/data/v1/post/${id}/comment`, {
headers: { "app-id": process.env.REACT_APP_API_KEY }
})
])
.then(
axios.spread((detail, comment) => {
setItem({ ...detail.data })
setComments([...comment.data.data])
})
)
.catch((detail_err, comment_err) => {
console.error(detail_err);
console.error(comment_err);
});
}, []);
我像上面一样设置了 State。 并且我试图在 return() 中使用 State,但似乎它没有等待数据集。
return (
<div>
{item.tags.map((tag, index) => {
return <Chip label={tag} key={index} />
})}
</div>
)
因为我收到这样的错误消息:Uncaught TypeError:无法读取未定义的属性(读取“map”)。 由于我初始化的“item”只是空的 {object},所以它无法读取“item.tags”,这是由 useEffect 中的 setState 设置的。
我如何等待数据集?
3个回答
一般来说,它会设置一个状态
isFetched
来确定来自 api 的数据是否已准备就绪。当
isFetched
等于
true
时,表示
item.tags
具有值。
const [isFetched, setIsFetched] = useState(false);
useEffect(async () => {
await axios.all(...).then(() => {
...
...
setIsFetched(true);
})
}, [])
// You could return null or an Loader component meaning the api is not ready
if (!isFetched) return null;
return (
<div>
{item.tags.map((tag, index) => {
return <Chip label={tag} key={index} />
})}
</div>
)
另一方面,您可以使用
可选链
来避免使用来自
undefined
值(即
item.tags
)的
map
,正确的方法是将
item.tags.map
替换为
item.tags?.map
。
bcjohn
2022-03-06
let [item, setItem] = useState({});
您的初始状态是一个空对象,并且始终会至少有一个渲染使用此初始状态。因此,您的代码需要能够在具有此状态时正常工作。例如,您可以在尝试使用 item.tags 之前检查它是否存在:
if (item.tags) {
return (
<div>
{item.tags.map((tag, index) => {
return <Chip label={tag} key={index] />
})}
</div>
);
} else {
return <div>Loading...</div>
}
或者,您可以更改初始状态,使其具有与加载完成后相同的形状:
let [item, setItem] = useState({ tags: [] });
Nicholas Tower
2022-03-06
最初,
item
是一个空的 JSON (
{})。您应该使用
可选链接运算符
(
?.
) 轻松摆脱 null 或未定义的异常。
return (
<div>
{item?.tags?.map((tag, index) => {
return <Chip label={tag} key={index} />
})}
</div>
)
Amila Senadheera
2022-03-06