skip to Main Content

I have a tree, so when a user clicks on the root, the table will automatically display the first item of that root node.

The problem arises when the user clicks too quickly, even before the API tree returns data containing the first item.

So I came up with the idea:

so I came up with the idea

const getFirstItemAsync = useCallback(async () => {
    while (isEmpty(tree?.[0]?.items)) {
      await new Promise((resolve) => setTimeout(resolve, 1000));
    }
    return tree?.[0]?.items?.[0];
  }, [tree]);

And this is my function to fetch data tree

const loadItemsFn = useCallback(
    (item: A, targetId: string, isExpand: boolean = true) => {
      if (loadItems) {
        loadItems(params).then(
          (data: ITreePayload<ITreeItem>) => {
            setTree(data)
          }
        );
      }
    },
    [loadItems, tree ]
  );

However, I think there is a way to track when the API call is ready and await until the API has returned.

2

Answers


  1. You could do something like the following

    const [isTreeLoading, setIsTreeLoading] = useState(false);
    const loadItemsFn = useCallback(
        (item: A, targetId: string, isExpand: boolean = true) => {
          if (loadItems) {
            setIsTreeLoading(true);
            loadItems(params).then(
              (data: ITreePayload<ITreeItem>) => {
                setTree(data)
              }
            ).finally(()=>{
              setIsTreeLoading(false);
            })
          }
        },
        [loadItems, tree ]
      );
    
    // now you can use the isTreeLoading variable whenever you want to 
    

    This is a initial approach to this issue, just to give the general idea. In reality you should have to check/handle for errors of the request etc.

    There are libraries that can provide much of this out of the box, like TanStack query (previously known as react-query)

    Login or Signup to reply.
  2. You can use a state with a time out to prevent quick click of the user

    const [isProcessing, setIsProcessing] = useState<boolean>(false);
    
    const handleLoadItemsFn = async () => {
        if(isProcessing)
        {
            return;
        }
        setIsProcessing(true);
        try{
            loadItemsFn(); // pass your parameter
        }
        catch(error)
        {
            setTimeout(() => {
                setIsProcessing(false);
            }, 1000);
        }
        finally
        {
            setTimeout(() => {
                setIsProcessing(false);
            }, 1000);
        }
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search