![](/img/trans.png)
[英]Is this the proper way to wait for this function to finish before calling it again?(React-Native)
[英]Proper way to wait for a function to finish or data to load before rendering in React?
我有以下反应代码,它从 api 中提取一些数据并输出它。 在result['track_list']
中,我收到带有时间戳的曲目列表,在aggTrackList()
中,我根据日/月/年将数据聚合到键值对中,然后在我创建的 Card 组件中显示聚合数据。
import React, { useState, useEffect } from "react";
function App() {
const [error, setError] = useState(null);
const [isLoaded, setIsLoaded] = useState(false);
const [trackList, settracks] = useState([]);
const [sortby, setSortby] = useState("day");
const [sortedList, setSortedList] = useState([]);
useEffect(() => {
aggTrackList();
}, [sortby]);
const aggTrackList = () => {
setSortedList([]);
let sortedObj = {};
switch (sortby) {
case "day":
trackList.forEach((track) => {
let dayVal = new Date(track[3]).toDateString();
dayVal in sortedObj
? sortedObj[dayVal].push(track)
: (sortedObj[dayVal] = [track]);
});
setSortedList(sortedObj);
break;
case "month":
trackList.forEach((track) => {
let monthVal = new Date(track[3]).toDateString().split(" ");
let monthYear = monthVal[1] + monthVal[3];
monthYear in sortedObj
? sortedObj[monthYear].push(track)
: (sortedObj[monthYear] = [track]);
});
setSortedList(sortedObj);
break;
case "year":
trackList.forEach((track) => {
let yearVal = new Date(track[3]).toDateString().split(" ");
let year = yearVal[3];
year in sortedObj
? sortedObj[year].push(track)
: (sortedObj[year] = [track]);
});
setSortedList(sortedObj);
break;
}
};
const getUserTracks = (username) => {
fetch(`http://localhost/my/api/${username}`, {
headers: {
"Content-Type": "application/json",
Accept: "application/json",
},
})
.then((res) => res.json())
.then(
(result) => {
settracks(result["tracks_played"]);
aggTrackList();
setIsLoaded(true);
},
(error) => {
console.log(error);
setIsLoaded(true);
setError(error);
}
);
};
return (
<div className="App">
<SortMenu
setSort={(selected) => {
setSortby(selected);
}}
/>
<UserForm onSubmit={getUserTracks} />
<div className="trackList">
{isLoaded ? (
Object.entries(sortedList).map(([day, track]) => (
<Card
className="card"
displayMode={sortby}
key={day}
timestamp={day}
content={track}
/>
))
) : (
<div>...</div>
)}
</div>
</div>
);
}
export default App;
我遇到的问题是提交UserForm
并接收数据时。 除非我在加载数据后单击排序菜单选项之一来更新sortby
state,否则卡片元素不会呈现。 如何让数据在加载后自动显示?
我正在创建这个项目来学习 React,所以如果有什么可以做得更好或者我做错了什么,请告诉我。
谢谢。
编辑:我在代码框上的代码 - https://codesandbox.io/s/fervent-minsky-bjko8?file=/src/App.js带有来自我的 API 的示例数据。
您可以通过两种方式做到这一点:
useLayoutEffect
这里需要注意的是,首先执行钩子传递的function,然后渲染组件。
useLayoutEffect
中进行 API 调用,然后在从 API 获得响应后设置数据。 数据最初可以在哪里const [data, setData] = useState(null)
JSX 必须适当地处理来自服务器的不同响应的所有情况。
useEffect
这里要注意的是,这个 function 在组件渲染之后运行。
useEffect
挂钩中进行 API 调用。 获得数据后,相应地设置 state 变量。在这里,您的 jsx 可能类似于
{
data === null ? (
<Loader />
) : data.length > 0 ? (
<Table data={data} />
) : (
<NoDataPlaceholder />
)
}
在这里,我假设数据是对象列表。 但适当的条件可以用于任何其他格式。 在这里,当使用 useEffect 中的useEffect
调用获取数据时,用户将看到加载 animation。 获取数据后,将向用户显示数据。 如果数据为空,将向用户显示适当的占位符消息。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.