MobX 和观察对象及其作为函数的属性

时间:2021-01-26 18:04:29

标签: javascript reactjs mobx

我不知道我是否可以清晰易读地呈现我的问题。 让我先介绍一下...

...本质

我创建了一个 Mobx 商店,我在其中存储有关对话框的信息。这很简单,所以让我在这里完整引用它。

import { makeObservable, action, computed, observable } from "mobx";

class WindowsStore {
    windowsList = [];

    constructor() {
        makeObservable(this, {
            windowsList: observable,
            addWindow: action,
            removeWindowById: action,
            windows: computed,
        });
    }

    addWindow(uniqueId, component, props) {
        this.windowsList.push({ 
            id: uniqueId,
            Win: [component],
            props
        });
    }

    removeWindowById(wndId) {
        const wndIndex = this.windowsList.findIndex((wnd) => wnd.id === wndId);
        if (wndIndex > -1) this.windowsList.splice(wndIndex, 1);
    }

    get windows() {
        return this.windowsList; <-- is't sick, but I don't like mobx strict-mode warnings
    }
}

const windowsStore = (window.windowsStore = new WindowsStore());

export default windowsStore;

我想要这样的结构,因为它需要将所有对话框作为子组件放置在一个组件中(我将在下面介绍)

const WindowsList = observer(({ windowsStore }) => {
    return windowsStore.windows.map((wnd) => {
        const Win = wnd.Win[0]; <-- it's weird (I know it) but that's the only way it wants to work
        return (
            <Win
                {...wnd.props}
                key={wnd.id}
                onClose={() => {
                    WindowsStore.removeWindowById(wnd.id);
                }}
            />
        );
    });
});

然后,在需要的地方调用组件 <WindowsList windowsStore = {WindowsStore} />,瞧。

现在,在应用程序的任何地方,它都会调用 store addWindow (uniqueId, component_class, props) 来调用对话框。

接下来会发生什么。变量 props(通常作为对象)作为属性传递给 component_class(如上面 <WindowsList /> 组件的主体所示)

确实有效。

我的问题

但是,我在 props 中传递函数时遇到问题,例如:

// ...somewhere in dialog component...
    doDelete(e) {
        console.log("Deleting...");
    }

    openDeleteConfirm = (item) => {
        const filepath = combinePathName(item.path, item.name);
        WindowsStore.addWindow("delete-" + filepath, DeleteConfirmation, {
            item: filepath,
            onConfirm: this.doDelete, <-- this is my problem :(
        });
    };

我注意到,在对话框组件中没有传递 onConfirm 属性,即使它在 store.windowsList 中可见。这是控制台输出:

> windowsStore.windowsList[0].props
Proxy {Symbol(mobx administration): ObservableObjectAdministration, onConfirm: ƒ}
    [[Handler]]: Object
    [[Target]]: Object
        item: (...)
        onConfirm: ƒ res() <-- Here!
        Symbol(mobx administration): ObservableObjectAdministration {target_: {…}, values_: Map(1), name_: "WindowsStore@206.windowsList[..].props", keysAtom_: Atom, defaultEnhancer_: ƒ, …}
        get item: ƒ ()
        set item: ƒ (v)
        __proto__: Object
    [[IsRevoked]]: false

如何通过 store 将函数作为其属性传递给组件? 甚至有可能吗?

帮助,因为我有点迷路了;)

1 个答案:

答案 0 :(得分:0)

这不是解决方案

部分地,我设法解决了我的问题,但是它不精确,我担心它可能会导致其他问题(将来)

诀窍

我决定像这样在 actions 数组中放置一个指向操作的指针:

// ...somewhere in dialog component...

    doDelete({ path, name }) {
        console.log(`Delete entry ${name} in ${path}...`);
    }

    openDeleteConfirm = (item) => {
        const filepath = combinePathName(item.path, item.name);
        WindowsStore.addWindow("delete-" + filepath, DeleteConfirmation, {
            item: filepath,
            actions: [
                () => {
                    this.doDelete(item);
                },
            ],
        });
    };

在对话框代码中,由 actions 数组中的索引引用:

    this.props.actions[0]();

它有效,但我不喜欢它:/