我正在尝试实现一个钩子(useFetch(route, dependencies=[])
),该钩子将用于fetch
数据并返回标量值loading
,该值用于确定用户当前是否正在获取新数据。
这可以在初始渲染上按预期方式工作(因为loading
的默认状态为true)。
在每个后续渲染中都会发生此问题。由于loading
状态当前设置为false
(在初始渲染之后),因此loading
状态将在额外的渲染周期内保持为false,然后再在useEffect()
的顶部更新为true。
如何防止出现额外的loading=false
渲染周期,因此使用此useFetch()
的组件会立即意识到当前正在提取数据,并且可以在'...loading'
中显示render()
文本(而不必渲染两次以达到这一点)。
useFetch
function useFetch(route, successHandler, dependencies = []) {
const [loading, setLoading] = useState(true);
useEffect(() => {
setLoading(true);
fetch(route,
{
method: 'POST',
body: JSON.stringify({}),
headers: {"Content-Type": "application/json"}
})
.then(res => res.json())
.then(
() => {
// Set state data from component here
successHandler();
},
() => {/*...*/})
.finally(() => {
setLoading(false);
});
}, dependencies);
return loading;
}
零件
function Component(){
const [toggle, setToggle] = useState(false);
const [options, setOptions] = useState({});
const loading = useFetch('endpoint',
() => setOptions({foo: 'bar'}),
[toggle]);
return <div>
<button onClick={()=>{setToggle(!toggle)}}>Trigger useFetch()</button>
{loading ? '...loading': options.foo}
</div>;
}
任何帮助或设计建议,将不胜感激,
最佳答案
您的代码有两个错误:
const loading = useFetch('endpoint',
() => setOptions({foo: 'bar'}),
[toggle]);
依赖项数组应该是
useEffect
中使用的变量,在您的情况下,它可以是[route]
[toggle]
作为依赖项参数将发送[false]
或[true]
,具体取决于您的状态变量。这将不受您创建的钩子的useEffect的控制。看看这个例子,它可以帮助您更好地理解: