用 mobx 反应 Sortable JS

Posted

技术标签:

【中文标题】用 mobx 反应 Sortable JS【英文标题】:React Sortable JS with mobx 【发布时间】:2020-12-07 00:10:10 【问题描述】:

我正在构建一个功能组件,该组件应该使用 react-sortablejs 来自 mobx 存储的计算数组(层数组)呈现可排序组件(ReactSortable)。组件在应用程序加载时呈现,但在通过拖放元素重新排列数组时,出现以下错误:

mobx.module.js:89 未捕获错误:[mobx] 由于启用了严格模式,因此不允许在操作之外更改观察到的可观察值。如果打算进行此更改,请将代码包装在 action 中。尝试修改:LayerStore@23.layersRegistry.9f332395-6bfe-4c3f-a496-8804e1dec490.chosen? 实际上,layers 数组是从 store 中的 layersRegistry Map observable 计算出来的,如下面的代码所示,但是在对层进行排序时,我并没有更改 layersRegistry observable;这就是我对错误感到困惑的原因。

在这种情况下有什么问题,我该如何解决它,以便当我重新使用图层(通过拖放)时,商店中的图层变量或 layerRegistry Map 可观察值会根据排序进行更新? 这里是组件的代码

import React,  useContext, useEffect, Fragment, useState  from "react";
import  RootStoreContext  from "../../../app/stores/rootStore";
import  observer  from "mobx-react-lite";
import LayerListItem from "./LayerListItem";
import  ReactSortable  from "react-sortablejs";

export const LayersDashboard = () => 
  const rootStore = useContext(RootStoreContext);
  const  layers, loadLayers  = rootStore.layerstore;
  useEffect(() => 
    loadLayers();
  , [loadLayers]);

  const [items, setItems] = useState(layers);

  return (
    <Fragment>
      <ReactSortable list=layers setList=setItems>
        layers.map((layer) => (
          <LayerListItem key=layer.id layer=layer />
        ))
      </ReactSortable>
    </Fragment>
  );
;

export default observer(LayersDashboard);

这是商店的代码

import  observable, action, runInAction, computed  from "mobx";
import agent from "../api/agent";
import  RootStore  from "./rootStore";
import  ILayer  from "../models/Layer";

export default class LayerStore 
  rootStore: RootStore;
  constructor(rootStore: RootStore) 
    this.rootStore = rootStore;
  

  @observable layersRegistry = new Map();


  @computed get layers() 
    return Array.from(this.layersRegistry.values());
  

  @action loadLayers = async () => 
    try 
    
      const layers = await agent.Layers.list();
      runInAction(() => 
      
        layers.forEach((layer) => 
          this.layersRegistry.set(layer.id, layer);
        );

      );
     catch (error) 
      runInAction(() => 
        console.log("error");
      );
    
  ;

 

【问题讨论】:

【参考方案1】:

我建议在将数据传递给 ReactSortable 或任何其他库之前对您的数据调用 toJS 并使您的可观察数据与可排序数据保持同步,您需要使用一些 onDragEnd 事件挂钩并从那里调用 mobx 操作更新可观察数据。但是我不确定 react-sortablejs 是否支持这个事件钩子。

【讨论】:

其实这行不通。相反,我使用了带有 onSortEnd 的 React Sortable 钩子,该钩子通过商店中的 mobx 操作修改了 observable,并且成功了。

以上是关于用 mobx 反应 Sortable JS的主要内容,如果未能解决你的问题,请参考以下文章

如何在反应原生 mobx 中设置数组值?

当我设置 observable 时,mobx-react 观察者不会触发

用户可以更改 Chrome 中 Redux/Mobx 的值以访问受限视图吗?

Mobx | 强大的状态管理工具 | 可以用Mobx来替代掉redux

mobx基本概念

不懂函数式?用 mobx 来写 react 应用吧