Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[RFC] useLoading #1745

Open
Dav3rs opened this issue Jul 7, 2022 · 8 comments
Open

[RFC] useLoading #1745

Dav3rs opened this issue Jul 7, 2022 · 8 comments

Comments

@Dav3rs
Copy link

Dav3rs commented Jul 7, 2022

Hook to track the loading state of async functions.

const [fn, loading] = useLoading(fn)

Example:

function Button({ onClick, children }) {
    const [clickHandler, loading] = useLoading(onClick);
  
    return <button onClick={clickHandler}>{loading ? "Loading..." : children}</button>;
}

Other Example:

function Form({ onSave }) {
    const [handleSave, saving] = useLoading(onSave);
  
    return (
        <>
            ...
            ...
            <button onClick={handleSave}>{saving ? "Saving..." : "Save"}</button>
        </>
    );
}

A posible implementation could look like this:

function useLoading(fn) {
    const [loading, setLoading] = useState(false);
  
    const _fn = useMemoizedFn(async (...args) => {
        setLoading(true);
        const result = await fn(...args);
        setLoading(false);
        return result;
    });
  
    return [_fn, loading];
}
@miracles1919
Copy link
Collaborator

what's the difference with useRequest

@Dav3rs
Copy link
Author

Dav3rs commented Jul 8, 2022

useLoading is not for data fetching, but for traking the loading state of any async function, the returned function can be hooked again in the component tree level. Like this:

async function doSomethingFor5Seconds() {
  //...
}

// Parent Component
const [doSomething, doingIt] = useLoading(doSomethingFor5Seconds);

// Child Component
const [handleDo, inProgress] = useLoading(doSomething);

// SubChild Component
const [onClick, loading] = useLoading(handleDo);

// Remember the tuple is [Function, boolean] with any apropiate variable name

@Dav3rs
Copy link
Author

Dav3rs commented Jul 9, 2022

Currently using this approach, because it stucked loading forever on errors.

export default function useLoading<F extends (...args: any) => Promise<any>>(f: F): [F, boolean] {
  const [loading, setLoading] = useState(false);
  const _f = useMemoizedFn(async (...args: any) => {
    setLoading(true);
    try {
      return await f(...args);
    } catch (error) {
      throw error;
    } finally {
      setLoading(false);
    }
  });
  return [_f as any, loading];
}

@miracles1919
Copy link
Collaborator

useLoading is not for data fetching, but for traking the loading state of any async function

useRequest is not only for data fetching, but also can track the loading state of any async function

async function doSomethingFor5Seconds() {
  //...
}

// manual trigger
const { loading, run } = useRequest(doSomethingFor5Seconds, {
  manual: true
});

it stucked loading forever on errors.

useRequest manages the status of loading, error, users can handle different situations according to the status

const {  error, loading } = useRequest(getUsername);

if (error) { ... }
if (loading) { ... }

@Dav3rs
Copy link
Author

Dav3rs commented Jul 11, 2022

Didn't know, but it is still looking to much verbose to rename variables and the word "request" in places where maybe there are not requests. But good to know.

@Dav3rs Dav3rs closed this as completed Jul 11, 2022
@Sunny-117
Copy link

I also think useLoading should exist

@Sunny-117
Copy link

I also think the component DelayLoading will be better

@Dav3rs
Copy link
Author

Dav3rs commented Dec 15, 2022

Indeed!

@Dav3rs Dav3rs reopened this Dec 15, 2022
@liuyib liuyib changed the title useLoading [RFC] useLoading Oct 17, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants