为什么mobx @computed值不?

时间:2019-09-09 21:15:53

标签: javascript reactjs mobx mobx-react

简单:计算值引用的可观察值发生更改时不会更新。

import {observable,computed,action} from 'mobx';

export default class anObject {

    // THESE WRITTEN CHARACTERISTICS ARE MANDATORY
    @observable attributes = {}; // {attribute : [values]}
    @observable attributeOrder = {}; // {attribute: order-index}
    @observable attributeToggle = {}; // {attribute : bool}


    @computed get orderedAttributeKeys() {
        const orderedAttributeKeys = [];

        Object.entries(this.attributeOrder).forEach(
            ([attrName, index]) => orderedAttributeKeys[index] = attrName
        );

        return orderedAttributeKeys;
    };

    changeAttribute = (existingAttr, newAttr) => {
        this.attributes[newAttr] = this.attributes[existingAttr].slice(0);
        delete this.attributes[existingAttr];

        this.attributeOrder[newAttr] = this.attributeOrder[existingAttr];
        delete this.attributeOrder[existingAttr];

        this.attributeToggle[newAttr] = this.attributeToggle[existingAttr];
        delete this.attributeToggle[existingAttr];

        console.log(this.orderedAttributeKeys)
    };

}

在调用changeAttribute之后,this.orderedAttributeKeys不返回新值。该节点显示不变。

但是,如果我删除@computed并将其设为普通(非getter)函数,则出于某种原因,this.orderedAttributeKeys确实会显示新值。为什么会这样?

编辑:添加了更多信息

它会通过日志和调试工具更新判断,但不会在屏幕上呈现(以下组件具有此代码,但不会重新呈现)。为什么?

{/* ATTRIBUTES */}
<div>
    <h5>Attributes</h5>
    {
    this.props.appStore.repo.canvas.pointerToObjectAboveInCanvas.orderedAttributeKeys.map((attr) => { return <Attribute node={node} attribute={attr} key={attr}/>})
    }
</div>

pointerToObjectAboveInCanvas是一个变量。它已设置为指向上方的对象。

在此模式中调用anObject中的changeAttribute函数。以此方法从Attribute组件开始

    handleAttrKeyChange = async (existingKey, newKey) => {
        await this.canvas.updateNodeAttrKey(this.props.node, existingKey, newKey);
        this.setState({attributeEdit: false}); // The Attribute component re-renders (we change from an Input holding the attribute prop, to a div. But the above component which calls Attribute doesn't re-render, so the attribute prop is the same
    };

在另一个对象(this.canvas)中调用此方法

    updateNodeAttrKey = (node, existingKey, newKey) => {
        if (existingKey === newKey) { return { success: true } }
        else if (newKey === "") { return { success: false, errors: [{msg: "If you'd like to delete this attribute, click on the red cross to the right!"}] } }

        node.changeAttribute(existingKey, newKey);

        return { success: true }
    };

为什么不保留属性重新呈现的组件?这就是所谓的orderedAttributeKeys!还是我问错了一个问题,另外一个问题是……

一个有趣的事实是,发生了相同的一组调用,以更改attributeValue(attribute是anObject的可观察字典中的键,attributeValue是值),但它却显示出来(因为Attribute组件重新渲染并直接从中提取节点的属性字典以提取值。这又是一个问题,属性键发生了变化,但是其外部的组件没有重新渲染,因此属性prop不变了!

2 个答案:

答案 0 :(得分:0)

这是因为您已经用changeAttribute装饰器装饰了@action

这意味着该功能内的所有可观察到的突变都在一次交易中发生-例如在控制台日志之后。

如果删除@action装饰器,则应该看到这些可观察对象在它们被调用的行上得到了更新,并且控制台日志应该与您期望的一样。

进一步阅读: https://mobx.js.org/refguide/action.html https://mobx.js.org/refguide/transaction.html

答案 1 :(得分:0)

尝试简化您的代码:

    @computed 
    get orderedAttributeKeys() {   
        const orderedAttributeKeys = [];

        Object.entries(this.attributeOrder).forEach(
            ([attrName, index]) => orderedAttributeKeys[index] = this.attributes[attrName])
        );

        return orderedAttributeKeys;
    };

    @action.bound
    changeAttribute(existingAttr, newAttr) {
        // ...
    };

还要重命名您的商店名称,保留对象export default class StoreName