#Can't get value from Tauri Command

7 messages · Page 1 of 1 (latest)

rustic lodge
#

I'm new to TS, React, and Tauri, so this question is a bit basic, but I can't seem to figure out how to do this.

System Info:

[⚠] Environment
    - OS: NixOS 23.11.0 X64
    ✔ webkit2gtk-4.0: 2.40.5
    ✔ rsvg2: 2.56.3
    ✔ rustc: 1.71.1 (eb26296b5 2023-08-03) (built from a source tarball)
    ✔ Cargo: 1.71.1
    ⚠ rustup: not installed!
      If you have rust installed some other way, we recommend uninstalling it
      then use rustup instead. Visit https://rustup.rs/
    ⚠ Rust toolchain: couldn't be deteceted!
      maybe you don't have rustup installed? if so, Visit https://rustup.rs/
    - node: 18.17.1
    - npm: 9.6.7

[-] Packages
    - tauri [RUST]: 1.4.1
    - tauri-build [RUST]: 1.4.0
    - wry [RUST]: 0.24.3
    - tao [RUST]: 0.16.2
    - @tauri-apps/api [NPM]: 1.4.0
    - @tauri-apps/cli [NPM]: 1.3.0 (outdated, latest: 1.4.0)

[-] App
    - build-type: bundle
    - CSP: unset
    - distDir: ../dist
    - devPath: http://localhost:5173/
    - framework: React
    - bundler: Vite

I've created a command like this:

#[tauri::command]
fn get_chart_data() -> [i32; 6] {
    [1, 2, 3, 4, 5, 6]
}

fn main() {
    tauri::Builder::default()
        .invoke_handler(tauri::generate_handler![get_chart_data])
        .run(tauri::generate_context!())
        .expect("error while running tauri application");
}
#

And then I have this in my app.tsx:

import "./App.css";
import { Doughnut } from "react-chartjs-2";
import { Chart as ChartJS, ArcElement, Tooltip, Legend } from "chart.js";
import { React, Component } from "react";

import { invoke } from "@tauri-apps/api";

ChartJS.register(ArcElement, Tooltip, Legend);

function CreateChart() {
  let chartData = invoke("get_chart_data").then((data) => data);
  console.log(chartData);

  const data = {
    datasets: [
      {
        label: "# of Votes",
        //data: [12, 19, 3, 5, 2, 3],
        data: chartData,
      },
    ],
  };

  return <Doughnut data={data} />;
}

function App() {
  return (
    <div>
      <CreateChart />
    </div>
  );
}

export default App;

#

My issue lies in trying to get the data from the tauri command into a variable where it can be used.

How do I return the value from the invoke command?

When I run the code above it just says that its a promise, not an array

dark torrent
#

What you are logging is the chartData object, not the data array. The response from invoke is always a Promise due to how the IPC was designed so that it would match across platforms. When using .then, all the code that needs access to the resolved variable has to be inside the .then, otherwise you face a severe risk of race conditions. For example:

let raceConditionValue;
let chartData = invoke("get_chart_data").then(
  (data) => {
    console.log("invoke get_chart_data resolved", data);
    raceConditionValue = data;
  },
  (rejected) => {
    console.log("invoke get_chart_data rejected", rejected);
  }
);
// May print "undefined" or the value without any predictability.
console.log("race condition", raceConditionValue);

The newer approach is to use await, which I believe is supported in all versions of the OS webviews that Tauri can run in. For example:

let data;
try {
  let chartData = invoke("get_chart_data");
  data = await chartData;
} catch (rejected) {
  console.log("invoke get_chart_data rejected", rejected);
  return;
}
// Will never race because the return in the catch prevents code from getting this far.
console.log("invoke get_chart_data resolved", data);
rustic lodge
#

I see. Ty!

#

Ok so to use await I would need to make CreateChart async right?

I set it up like this:

async function CreateChart() {
  //const [chartData, setChartData] = useState([1, 2, 3, 4, 5, 6]);
  let my_data;
  try {
    let chartData = invoke("get_chart_data");
    my_data = await chartData;
  } catch (rejected) {
    console.log("invoke get_chart_data rejected", rejected);
    return;
  }

  const data = {
    datasets: [
      {
        label: "# of Votes",
        data: chartData,
      },
    ],
  };

  return <Doughnut data={data} />;
}

But I get this error: