【问题标题】:mobx-deep-action with Typescript async/await functions and @action decorator带有 Typescript async/await 函数和 @action 装饰器的 mobx-deep-action
【发布时间】:2017-09-29 18:44:22
【问题描述】:

我正在努力正确设置我的项目以消除在useStrict(true) 中运行时出现的 mobx 错误

错误

mobx.module.js:2238 Uncaught (in promise) Error: [mobx] Invariant failed: Since strict-mode is enabled, changing observed observable values outside actions is not allowed. Please wrap the code in an `action` if this change is intended. Tried to modify: WikiStore@1.tags
    at invariant (mobx.module.js:2238)
    at fail (mobx.module.js:2233)
    at checkIfStateModificationsAreAllowed (mobx.module.js:2794)
    at ObservableValue.prepareNewValue (mobx.module.js:750)
    at setPropertyValue (mobx.module.js:1605)
    at WikiStore.set [as tags] (mobx.module.js:1575)
    at WikiStore.<anonymous> (WikiStore.tsx:25)
    at step (tslib.es6.js:91)
    at Object.next (tslib.es6.js:72)
    at fulfilled (tslib.es6.js:62)

我的设置编译了,但错误仍然存​​在,所以我的构建链中一定有错误。

我使用了 GitHub repo here 提供的信息,但都有些模糊。

.babelrc

{
"passPerPreset": true,
"presets": [
    {
        "plugins": ["transform-regenerator"]
    },
    {
        "plugins": ["mobx-deep-action"]
    },
    {
      "plugins": ["babel-plugin-transform-decorators-legacy"]
    },
    "es2015", "react", "stage-0"
]
}

webpack.config.js

const path = require("path");
const ExtractTextPlugin = require("extract-text-webpack-plugin");
const webpack = require("webpack");
const CheckerPlugin = require('awesome-typescript-loader').CheckerPlugin;

const clientBundleOutputDir = "./wwwroot/dist";

module.exports = (env) => {

    const clientConfig = {
        stats: { modules: false },
        entry: { "main-client": "./Client/index.tsx" },
        resolve: { extensions: [".js", ".jsx", ".ts", ".tsx" ] },
        output: {
            filename: "[name].js",
            path: path.join(__dirname, clientBundleOutputDir),
            publicPath: "/dist/"
        },
        module: {
            rules: [
                { test: /\.s?css$/, use: ["css-hot-loader"].concat(ExtractTextPlugin.extract({fallback: "style-loader", use: ["css-loader", "sass-loader"]})) },
                { test: /\.woff(2)?(\?v=[0-9]\.[0-9]\.[0-9])?$/, loader: "url-loader?limit=10000&mimetype=application/font-woff" },
                { test: /\.(ttf|eot|svg)(\?v=[0-9]\.[0-9]\.[0-9])?$/, loader: "file-loader" },
                { test: /\.(png|svg|jpg|gif|ico)$/, use: ["file-loader"] },
                // { test: /\.tsx?$/, include: /Client/, use: "awesome-typescript-loader?silent=true&useBabel=true&useCache=true" }
                { test: /\.tsx?$/, include: /Client/, use: ["babel-loader", "ts-loader"] }
            ]
        },
        plugins: [
            new CheckerPlugin(),
            new ExtractTextPlugin("site.css"),
            new webpack.SourceMapDevToolPlugin({
                filename: "[file].map",
                moduleFilenameTemplate: path.relative(clientBundleOutputDir, '[resourcePath]')
            })
        ]
    };

    return [clientConfig];
};

我已经尝试过很棒的 typescript loader 以及 ts-loader、babel-loader 组合。

这里是我的商店(短版)

import { autorun, observable, action } from "mobx";
import { Wiki } from "../models/Wiki";
import { Tag } from "../models/Tag";
import * as Api from "../api/api";

export class WikiStore {
    @observable public tags: Tag[] = [];

    constructor() {
        this.getTags();
    }

    @action
    public async getTags() {
        this.tags = await Api.getTags();
    }
}

export const wikiStore = new WikiStore();

当我从 React 组件调用 wikiStore.getTags() 时,我得到了错误。没有useStrict(true),一切都可以正常工作(如预期的那样)

也许有人有想法。

【问题讨论】:

  • 你检查mobx.js.org/best/actions.html了吗?
  • @mweststrate 是的,我从那里获得了 mobx-deep-action GitHub 存储库的链接
  • @mweststrate 好的,经过一个晚上,我一次又一次地阅读了文档。我现在看到,mobx-deep-action 解决了一个不同的问题,我必须使用 runInAction 将我的任务包装在另一个操作中。

标签: reactjs typescript mobx mobx-react


【解决方案1】:

我认为您仍然需要将await 和作业分开:

@action
public async getTags() {
  const tags = await Api.getTags();
  this.tags.replace(tags);
}

【讨论】:

  • 这确实防止了错误,但它不会触发我的 UI 的重新呈现。当我执行runInAction(() =&gt; this.tags = tags); 时,会发生重新渲染。缺少什么?
【解决方案2】:

请在此处阅读: https://mobx.js.org/best/actions.html#async-await

因此,@action 仅适用于代码块,直到第一个 await

所以const tags = await Api.getTags();必须重新包装

@action
public async getTags() {
    const tags = await Api.getTags();
    runInAction(() => {
      this.tags = tags;
    })
}

【讨论】:

    猜你喜欢
    • 2013-08-06
    • 1970-01-01
    • 2021-03-07
    • 2019-05-20
    • 2017-09-12
    • 2023-03-10
    • 2017-06-19
    • 2016-08-22
    • 2022-01-17
    相关资源
    最近更新 更多