#"invoke" seems to block rendering on a React component

6 messages · Page 1 of 1 (latest)

ruby bobcat
#

For some reason, calling invoke inside my component blocks the rendering of the entire component.

Strangely, when I call another function (setTimeout) that returns a promise in the same way with dummy data, I get the desired behavior (render a loading state for the initial null value, then update it to the actual value when it returns.

To be clear, the behavior I see with invoke is that the entire app hangs on the prior component, and until invoke returns a value nothing happens (the initial null value / loading state never occurs with invoke but it does with setTimeout). Here is the component.

import { invoke } from '@tauri-apps/api/tauri'

import { useEffect, useState } from "react";


function Balances() {
    const [balance, setBalance] = useState<null | string>(null);
    useEffect(() => {
        // Uncommenting this blocks the rendering of the entire component (???)
        // async function getBalance() {
        //     const b = await invoke("get_balance") as string;
        //     setBalance(b as string);
        // }
        // getBalance();

        // This equivalent delay of setting a dummy balance allows the component
        // to render as desured with balance=null (a loading state), and then 
        // 5 seconds later updates the balance value and re-renders successfully  
        async function getSleep() {
            console.log("started sleep");
            
            await setTimeout(() => {
                console.log("ended sleep");
                setBalance("199");
            }, 5000);
        }
        getSleep();
    }, [])
    return (
        <>
            {balance === null ? (
                "Loading"
            ) : (
            <div>
                {balance}
            </div>
            )}
        </>
    )
}

export default Balances
spiral stump
#

the component code likely doesn't matter at all.

Assuming that there's no bug in your frontend, the 2 issues are:
- the ipc (the communication channel between frontend and backend) works on the main thread which can freeze the ui if blocked. Reducing the amount of data send can help here.
- if your command is sync (== not an async fn) it will also run on the main thread, potentially freezing the UI until it's done.

#

tldr, make the command async by declaring it as async fn or #[tauri::command(async)] and see if that's enough.

ruby bobcat
#

Many thanks for the insanely fast response, blown away. Will try this.

#

Making the command async fixes the problem. Thanks again @spiral stump - if you have any tipping online I would be glad to tip you. If not, I am sending you good vibes and gratitude.

spiral stump
#

the good vibes are more than enough, thank you :D