Mobx-计算中的意外副作用

问题描述 投票:1回答:1

这里是MobX概念的新手,但以为我遵守了规则。当我运行createProject("Foo")时,出现此错误:

Error: [mobx] Computed values are not allowed to cause side effects by changing observables that are already being observed. Tried to modify: [email protected][..].children

我假设通过将原始节点分配给leafNodesrootNodes,我只是制作新的本地变量,但它认为我正在更改原始的@observable。构建上述数组时,我也曾尝试过Object.assign({}, node)且没有任何更改。我应该如何构造这种结构以防止这种副作用?我有一个带有id和parentId的对象的平面数组,这些对象描述了标准的树层次结构。 tree函数用实际对象替换id,并产生实际的嵌套结构。

import { decorate, observable, action, computed } from "mobx";
import remotedev from "mobx-remotedev";
import shortid from "shortid";

class ProjectsStore {
    projects = [];
    tasks = [];

    createProject = (projectName, parentId = null) => {
        const project = {
            type: "project",
            id: shortid.generate(),
            name: projectName,
            parentId: parentId,
            children: []
        };
        this.projects.push(project);
        return project;
    };

    createTask = (taskName, parentId = null) => {
        const task = {
            type: "task",
            id: shortid.generate(),
            name: taskName,
            parentId: parentId
        };
        this.tasks.push(task);
        return task;
    };

    get tree() {
        // Separate root nodes and all others (leaf nodes)
        let leafNodes = [];
        let rootNodes = this.projects.filter(node => {
            if (!node.parentId) {
                return node;
            } else {
                leafNodes.push(node);
                return false;
            }
        });
        // Merge the tasks and non-root projects
        leafNodes = leafNodes.concat(this.tasks);

        // If the current node is a project, RECURSIVELY add the child nodes to
        // it into the .children array
        const populate = node => {
            if (node.type === "project") {
                // Search all non-root nodes to see if their parentId matches the
                // current node's id. This designates it as a child of the current node.

                // THIS IS WHERE THE ERROR HAPPENS!
                node.children = leafNodes.filter(leaf => node.id === leaf.parentId);
                // ^^^^^^^^^^^^^^^^^^^^^^^^^^

                for (let i = 0; i < node.children.length; i++) {
                    node.children[i] = populate(node.children[i]);
                }
            }
            return node;
        };

        // Iterate over all root nodes and return their populated trees.
        return rootNodes.map((node, n) => {
            return populate(node);
        });
    }
}

decorate(ProjectsStore, {
    projects: observable,
    tasks: observable,
    createProject: action,
    createTask: action,
    tree: computed
});

export default remotedev(ProjectsStore);
mobx mobx-react
1个回答
0
投票

解决了我自己的问题(种类)。因此,我已经学会了有关Mobx和代理的TON来尝试解决此问题,似乎最好的解决方案是架构更改。我以为可以将节点存储在平面数组中,然后使用递归函数动态构建层次结构。事实证明,我无法更改compute函数的结构(上面的错误^^),并且我无法复制节点,因为那样会破坏observe-能力。

因此,解决方案是使它们保持平坦并更改我的React组件渲染以递归渲染层次结构。 结果使数据和逻辑与表示分离。双赢!

© www.soinside.com 2019 - 2024. All rights reserved.