Javascript 反应:如何优化共享数据的自定义挂钩?
我有一个与以下类似的自定义挂钩:Javascript 反应:如何优化共享数据的自定义挂钩?,javascript,reactjs,request,axios,Javascript,Reactjs,Request,Axios,我有一个与以下类似的自定义挂钩: import { useEffect, useState } from 'react'; import axios from 'axios'; const myCustomHook = () => { const [countries, setCountries] = useState([]); const [isLoading, setLoading] = useState(true); useEffect(() => {
import { useEffect, useState } from 'react';
import axios from 'axios';
const myCustomHook = () => {
const [countries, setCountries] = useState([]);
const [isLoading, setLoading] = useState(true);
useEffect(() => {
(async () =>
await axios
.get("MY_API/countries")
.then(response => setCountries(response.data))
.finally(() => setLoading(false)))();
}, []);
return countries;
};
export default myCustomHook;
钩子工作得很好,但是我在我的应用程序的三个不同的领域使用它,尽管事实上,所有使用钩子的国家都是相同的
是否有一种好的模式可以只调用一次axios请求而不是三次
编辑-解决方案后的最终代码
import { useEffect, useState } from 'react';
import axios from 'axios';
let fakeCache = {
alreadyCalled: false,
countries: []
};
const myCustomHook = (forceUpdate = false) => {
const [isLoading, setLoading] = useState(true);
if (!fakeCache.alreadyCalled || forceUpdate) {
fakeCache.alreadyCalled = true;
(async () =>
await axios
.get("MY_API/countries")
.then(response => setCountries(response.data))
.finally(() => setLoading(false)))();
}
return countries;
};
export default myCustomHook;
一个解决方案是引入一个定制的“缓存层”(在钩子和axios请求之间),该层:
coutries
数据getCountries()
函数,在单独的模块中实现该缓存逻辑,然后从钩子调用该函数:
countries.js
import axios from 'axios';
// Module scoped variable that holds caches data
let cachedData = undefined;
// Example function wraps network request with caching layer
export const getCountries = async() => {
// We expect the data for countries to be an array. If cachedData
// is not an array, attempt to populate the cache with data
if (!Array.isArray(cachedData)) {
const response = await axios.get("MY_API/countries");
// Populate the cache with data returned from request
cachedData = response.data;
}
return cachedData;
}
import { useEffect, useState } from 'react';
import { getCountries } from "/countries";
const myCustomHook = () => {
const [countries, setCountries] = useState([]);
const [isLoading, setLoading] = useState(true);
useEffect(() => {
(async() => {
try {
setLoading(true);
// Update hooks state with countries data (cached or fresh)
setCountries(await getCountries());
} finally {
setLoading(false)
}
}, []);
});
}
export default myCustomHook;
myCustomHook.js
import axios from 'axios';
// Module scoped variable that holds caches data
let cachedData = undefined;
// Example function wraps network request with caching layer
export const getCountries = async() => {
// We expect the data for countries to be an array. If cachedData
// is not an array, attempt to populate the cache with data
if (!Array.isArray(cachedData)) {
const response = await axios.get("MY_API/countries");
// Populate the cache with data returned from request
cachedData = response.data;
}
return cachedData;
}
import { useEffect, useState } from 'react';
import { getCountries } from "/countries";
const myCustomHook = () => {
const [countries, setCountries] = useState([]);
const [isLoading, setLoading] = useState(true);
useEffect(() => {
(async() => {
try {
setLoading(true);
// Update hooks state with countries data (cached or fresh)
setCountries(await getCountries());
} finally {
setLoading(false)
}
}, []);
});
}
export default myCustomHook;
组件的每个实例都彼此独立运行 即使第一个实例的状态已填充了
国家/地区
,第二个实例仍不知道它,并且仍然为空
您可以将
国家
作为道具消费,如果为空则调用效果,否则只需从道具返回国家
我不喜欢那种百分之百的解决方案。我觉得很奇怪,组件或钩子更改了不在其作用域内的变量。但我想不出比这更好的办法来解决这个问题了。谢谢。我投票结束这个问题,因为它属于我的。