How to store a filepath in Tauri State?

Hi, I'm using Tauri to open a file using tauri::api::dialog::FileDialogBuilder.
Here is the code example in Tauri:

use tauri::api::dialog::FileDialogBuilder;
tauri::Builder::default()
  .build(tauri::generate_context!("test/fixture/src-tauri/tauri.conf.json"))
  .expect("failed to build tauri app")
  .run(|_app, _event| {
    FileDialogBuilder::new().pick_file(|file_path| {
      // do something with the optional file path here
      // the file path is `None` if the user closed the dialog
    })
  })

But, I want to store the file_path in Tauri State. Like this:

use tauri::State;
struct AppState(Mutex<String>);

So I write my function like this:

#[tauri::command]
fn open_file(app_state: State<AppState>) {
    dialog::FileDialogBuilder::new().pick_file(|file_path| {
        if let Some(path) = file_path {
            *app_state.0.lock().unwrap() = path.to_str().unwrap().to_string();
        }
    });
}

The problem is, the compiler said: app_state is a reference that is only valid in the function body has type State<'1, AppState>.
And, suggests moving the app_state in the closure. but it didn't work.
I have tried lots of ways, but neither of them works.

  1. I tried to take the file_path var out of the closure, not working.
  2. I tried to use the reference of app_state, not working.

Perhaps just because I don't know how to do it correctly.

Please help me.

If you want, here is the error message:

error[E0521]: borrowed data escapes outside of function     
  --> src\main.rs:14:21
   |
13 |   fn open_project(app_state: State<AppState>) {
   |                   ---------
   |                   |
   |                   `app_state` is a reference that is only valid in the function body
   |                   has type `State<'1, AppState>`
14 |       let file_path = dialog::FileDialogBuilder::new().pick_file(|file_path| {
   |  _____________________^
15 | |         if let Some(path) = file_path {
16 | |             *app_state.0.lock().unwrap() = path.to_str().unwrap().to_string();
17 | |         }
18 | |     });
   | |      ^
   | |      |
   | |______`app_state` escapes the function body here
   |        argument requires that `'1` must outlive `'static`

error[E0373]: closure may outlive the current function, but it borrows `app_state`, which is owned by the current function
  --> src\main.rs:14:64
   |
14 |     let file_path = dialog::FileDialogBuilder::new().pick_file(|file_path| {
   |                                                                ^^^^^^^^^^^ may outlive borrowed value `app_state`
15 |         if let Some(path) = file_path {
16 |             *app_state.0.lock().unwrap() = path.to_str().unwrap().to_string();
   |              --------- `app_state` is borrowed here
   |
note: function requires argument type to outlive `'static`
  --> src\main.rs:14:21
   |
14 |       let file_path = dialog::FileDialogBuilder::new().pick_file(|file_path| {
   |  _____________________^
15 | |         if let Some(path) = file_path {
16 | |             *app_state.0.lock().unwrap() = path.to_str().unwrap().to_string();
17 | |         }
18 | |     });
   | |______^
help: to force the closure to take ownership of `app_state` (and any other referenced variables), use the `move` keyword
   |
14 |     let file_path = dialog::FileDialogBuilder::new().pick_file(move |file_path| {
   |                                                                ++++

Try using an Arc<Mutex<String>> instead so it has a stable memory location. Then you can clone the Arc and move the copy into the closure.

It works! Thanks!!

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.