我正在尝试实现一个钩子(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的控制。


看看这个例子,它可以帮助您更好地理解:

javascript - React:实现一个钩子(Hook)以获取数据并返回加载状态-LMLPHP

07-24 18:58
查看更多