我正在尝试实现以下简单模式:
GET
列表- 输入新项目,保存
- 提出
POST
请求 - 对更新数据提出新的
GET
请求
从这里的代码开始,
const useApi = () => {
const [data, setData] = useState({ hits: [] });
const [url, setUrl] = useState(
'https://hn.algolia.com/api/v1/search?query=redux',
);
useEffect(() => {
const fetchData = async () => {
const result = await axios(url);
setData(result.data);
};
fetchData();
}, [url]);
return [{ data }, setUrl];
}
在页面装载上进行初始获取非常简单
const [{ data }, doFetch] = useDataApi(
'https://hn.algolia.com/api/v1/search?query=redux',
{ hits: [] },
);
但我不明白的是如何对数据进行"刷新"。由于没有有状态变量来确定钩子是否应该重新运行,因此如何在单击按钮时手动调用钩子?
使用单独的变量,如简单的计数机制:
const [count, setCount] = useState(0);
<button onClick={() => setCount(count + 1)} />
然后使用"count"作为有状态变量,以及url(如果用户搜索了不同的东西(:
useEffect(() => {
const fetchData = async () => {
const result = await axios(url);
setData(result.data);
};
fetchData();
}, [url, count]);
这是一种不同的方法。也许有更好的方法,但在这种情况下,它似乎有效。
您可以从useDataApi
返回fetchData
,然后在onClick
处理程序中使用它,并在useRef
的帮助下查找 URL 更改。为此,您应该fetchData
移到useEffect
之外并用useCallback
包裹
...
const fetchData = useCallback(
async () => {
setIsError(false);
setIsLoading(true);
try {
const result = await axios(url);
setData(result.data);
} catch (error) {
setIsError(true);
}
setIsLoading(false);
},
[url],
);
useEffect(() => {
fetchData();
}, [url, fetchData]); // add fetchData here as a second dependency
return [{ data, isLoading, isError }, setUrl, fetchData]; // add fetchData here as the third returned variable.
};
然后在您的应用程序中,您可以使用 refs 检查 URL 是否未更改:
function App() {
const [query, setQuery] = useState('redux');
const latestQuery = useRef(query); // define the ref
const [{ data, isLoading, isError }, doFetch, fetchData] = useDataApi(
'https://hn.algolia.com/api/v1/search?query=redux',
{ hits: [] },
);
return (
<Fragment>
<form
onSubmit={event => {
// check the query change
if (latestQuery.current === query) {
fetchData();
}
doFetch(
`https://hn.algolia.com/api/v1/search?query=${query}`,
);
// set current query to the ref value
latestQuery.current = query;
event.preventDefault();
}}
>
.....
我不太确定这是一个更好的解决方案,因为我自己还在学习钩子,太:)
我认为,如果在发出初始 api 请求后调度一个操作来获取可用的最新数据,则可以简化您描述的流程。随后,每次挂载组件时都应发出请求,这样组件就不负责确保它具有最新的数据。此流如下所示:
1(GET
列表
2(输入新项目,保存
3( 提出POST
请求
4( 让操作(在消费组件之外(处理响应,如果成功,则dispatch
操作以重新触发初始GET
列表调用,如果没有,则调用来处理错误。