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!!