Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/reactjs/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Reactjs 如何在会话存储中保存Mobx状态_Reactjs_Mobx_Mobx React - Fatal编程技术网

Reactjs 如何在会话存储中保存Mobx状态

Reactjs 如何在会话存储中保存Mobx状态,reactjs,mobx,mobx-react,Reactjs,Mobx,Mobx React,试图基本上实现这一点,这是为了Redux,但为了Mobx。最好使用sessionStorage。有没有一种简单的方法可以用最少的样板实现这一点?最简单的方法是在任何可观察到的属性发生变化时触发mobx“自动运行”。要做到这一点,你可以跟随 我将在这里放置一些示例代码,这些代码将帮助您开始: function autoSave(store, save) { let firstRun = true; mobx.autorun(() => { // This code will

试图基本上实现这一点,这是为了Redux,但为了Mobx。最好使用sessionStorage。有没有一种简单的方法可以用最少的样板实现这一点?

最简单的方法是在任何可观察到的属性发生变化时触发mobx“自动运行”。要做到这一点,你可以跟随

我将在这里放置一些示例代码,这些代码将帮助您开始:

function autoSave(store, save) {
  let firstRun = true;
  mobx.autorun(() => {
    // This code will run every time any observable property
    // on the store is updated.
    const json = JSON.stringify(mobx.toJS(store));
    if (!firstRun) {
      save(json);
    }
    firstRun = false;
  });
}

class MyStore {
  @mobx.observable prop1 = 999;
  @mobx.observable prop2 = [100, 200];

  constructor() {
    this.load();
    autoSave(this, this.save.bind(this));
  }

  load() {
    if (/* there is data in sessionStorage */) {
      const data = /* somehow get the data from sessionStorage or anywhere else */;
      mobx.extendObservable(this, data);
    }
  }

  save(json) {
    // Now you can do whatever you want with `json`.
    // e.g. save it to session storage.
    alert(json);
  }
}

在此发布示例:

这显示了一种更干净的检测值变化的方法,尽管不一定是本地存储

import {observable, autorun} from 'mobx';
import uuid from 'node-uuid';

export class TodoStore {
    authorStore;
    transportLayer;
    @observable todos = [];
    @observable isLoading = true;

    constructor(transportLayer, authorStore) {
        this.authorStore = authorStore; // Store that can resolve authors for us
        this.transportLayer = transportLayer; // Thing that can make server requests for us
        this.transportLayer.onReceiveTodoUpdate(updatedTodo => this.updateTodoFromServer(updatedTodo));
        this.loadTodos();
    }

    /**
     * Fetches all todo's from the server
     */
    loadTodos() {
        this.isLoading = true;
        this.transportLayer.fetchTodos().then(fetchedTodos => {
            fetchedTodos.forEach(json => this.updateTodoFromServer(json));
            this.isLoading = false;
        });
    }

    /**
     * Update a todo with information from the server. Guarantees a todo
     * only exists once. Might either construct a new todo, update an existing one,
     * or remove an todo if it has been deleted on the server.
     */
    updateTodoFromServer(json) {
        var todo = this.todos.find(todo => todo.id === json.id);
        if (!todo) {
            todo = new Todo(this, json.id);
            this.todos.push(todo);
        }
        if (json.isDeleted) {
            this.removeTodo(todo);
        } else {
            todo.updateFromJson(json);
        }
    }

    /**
     * Creates a fresh todo on the client and server
     */
    createTodo() {
        var todo = new Todo(this);
        this.todos.push(todo);
        return todo;
    }

    /**
     * A todo was somehow deleted, clean it from the client memory
     */
    removeTodo(todo) {
        this.todos.splice(this.todos.indexOf(todo), 1);
        todo.dispose();
    }
}

export class Todo {

    /**
     * unique id of this todo, immutable.
     */
    id = null;

    @observable completed = false;
    @observable task = "";

    /**
     * reference to an Author object (from the authorStore)
     */
    @observable author = null;

    store = null;

    /**
     * Indicates whether changes in this object
     * should be submitted to the server
     */
    autoSave = true;

    /**
     * Disposer for the side effect that automatically
     * stores this Todo, see @dispose.
     */
    saveHandler = null;

    constructor(store, id=uuid.v4()) {
        this.store = store;
        this.id = id;

        this.saveHandler = reaction(
            // observe everything that is used in the JSON:
            () => this.asJson,
            // if autoSave is on, send json to server
            (json) => {
                if (this.autoSave) {
                    this.store.transportLayer.saveTodo(json);
                }
            }
        );
    }

    /**
     * Remove this todo from the client and server
     */
    delete() {
        this.store.transportLayer.deleteTodo(this.id);
        this.store.removeTodo(this);
    }

    @computed get asJson() {
        return {
            id: this.id,
            completed: this.completed,
            task: this.task,
            authorId: this.author ? this.author.id : null
        };
    }

    /**
     * Update this todo with information from the server
     */
    updateFromJson(json) {
        // make sure our changes aren't send back to the server
        this.autoSave = false;
        this.completed = json.completed;
        this.task = json.task;
        this.author = this.store.authorStore.resolveAuthor(json.authorId);
        this.autoSave = true;
    }

    dispose() {
        // clean up the observer
        this.saveHandler();
    }
}

在这里,您可以使用我的代码,尽管它只支持本地存储,您应该能够非常轻松地修改它


事实证明,只需几行代码就可以做到这一点:

const store = observable({
    players: [
        "Player 1",
        "Player 2",
    ],
    // ...
})

reaction(() => JSON.stringify(store), json => {
    localStorage.setItem('store',json);
}, {
    delay: 500,
});

let json = localStorage.getItem('store');
if(json) {
    Object.assign(store, JSON.parse(json));
}

轰。刷新页面时不会丢失任何状态。如果有更改,则每500毫秒保存一次。

谢谢!如何在页面重新加载时重新加载状态?在构造函数中,在调用
autoSave()
之前,您可以读取会话存储并在存储实例上设置值。我刚刚编辑了答案,以提供更完整的解决方案。当然,您仍然需要进行一些更改才能使其适用于您的案例,但我希望这有助于您开始。在加载时,我遇到
错误:[mobx]“extendObservable”只能用于引入新属性。改为使用“设置”或“装饰”
如果启用了严格模式,则会出现错误,
不允许在操作之外更改观察到的值
@karianpour我认为您只需将其包装在
操作(()=>Object.assign(…))
中即可