REACT-如何高效地调用依赖异步操作



所以我有一个钩子,其中有一个按id调用统计信息的方法,还有一个调用可用统计信息列表的方法。

我想首先调用统计信息列表,然后根据第一个响应中第一个项目的id调用实际的统计数据。它看起来很光滑。像这样:

挂钩

const useMapStatistics = () => {
const [selectedStatistics, setSelectedStatistics] = useState(null); // maybe use a useRef here ?
const [allMapStatistics, setAllMapStatistics] = useState([]);
const [geoJSON, setGeoJSON] = useState({
type: "",
features: [],
});
const fetchMapStatisticsById = useCallback((type) => {
getMapStatisticsById({ type })
.then((result) => setGeoJSON(result));
},
[]
);
const fetchInitialMapStatistics = useCallback(() => {
getMapStatisticsList().then((list) => {
setAllMapStatistics(list.statistics);
setSelectedStatistics(list.statistics[0]);
return list.statistics[0];
})
.then((type) => fetchMapStatisticsById(type));
}, [fetchMapStatisticsById]);
useEffect(() => {
fetchInitialMapStatistics();
}, []);
return {
geoJSON,
allMapStatistics,
selectedStatistics,
fetchMapStatisticsById,
fetchInitialMapStatistics,
};
};

现在我在问自己,这是否是执行这项任务最有效的方法?我还试图在selectedStatistics状态下执行fetchMapStatisticsById,如下所示:

const fetchMapStatisticsById = useCallback(() => {
getMapStatisticsById({ type: selectedStatistics }) // selectedStatistics is null
.then(result =>  setGeoJSON(result));
}, [selectedStatistics]);

但这并没有起作用,因为将状态设置为react是异步发生的(selectedStatistics为null(。因此,我想知道是按id传递获取统计信息的状态(这对我来说不起作用(更好,还是在useCallback函数中仅将统计信息id作为参数传递更好?还可以选择将selectedStatistics放入useRef中,useRef将同步更改。这也是一种选择,还是这种反模式?

您提出了两种完成工作的方法,您想知道哪种更好,这取决于您的目的,因为您可能想知道它们不一样。

您可以这样做,但这意味着只有在调用fetchInitialMapStatistics时,才会在初始渲染时更改贴图统计信息。这意味着对selectedStatisticsId的更改不会导致mapStatistics和GeoJSON发生更改,这可能不是您想要的。

const fetchInitialMapStatistics = useCallback(() => {
getMapStatisticsList().then((list) => {
setAllMapStatistics(list.statistics);
setSelectedStatistics(list.statistics[0]);
return list.statistics[0];
})
.then((type) => fetchMapStatisticsById(type));
}, [fetchMapStatisticsById]);

另一方面,你也可以这样做,这意味着只要selectedId发生变化,你就想改变geoJSON的状态(这可能是你想要的(,顺便说一句,当selectedId发生变化时,你也应该实现一个转换状态,类似于加载器。

const fetchInitialMapStatistics = useCallback(() => {
getMapStatisticsList().then((list) => {
setAllMapStatistics(list.statistics);
setSelectedStatistics(list.statistics[0]);
return list.statistics[0];
})

}, []);
useEffect(() => {
if (selectedStatistics !== null) {
// anyway its better here to send the selected id as a param and not take it from state
// its better for at least three reasons that i can think of now
// - more readable code
// - easier code to test
// - your code is less subject to bugs related to misunderstanding of what the selectedId is
fetchMapStatisticsById(selectedStatistics);
}
}, [selectedStatistics]);

最新更新