0

我希望能够不为数据模型定义类型,但在加载数据后仍然能够观察数据。我也有关系,但可以静态定义它们。文档告诉我有关冻结的信息,但我需要这些条目是可观察的。没有它,我最好还是坚持我现在所拥有的。

我在以下评论中读到了一些关于动态模型类型的内容:https ://codeburst.io/the-curious-case-of-mobx-state-tree-7b4e22d461f 但因为我还没有使用过 mst 并且没有使用 ts 没有足够的信息让我了解他的确切含义。

mst 想要我做什么:

import React from "react";
import { render } from "react-dom";
import { types } from "mobx-state-tree";
import { observer } from "mobx-react";

const Todo = types.model({
  name: types.optional(types.string, ""),
  done: types.optional(types.boolean, false)
});

const eat = Todo.create({ name: "eat" });
render(
  <div>
    Eat TODO: {JSON.stringify(eat)}
  </div>,
  document.getElementById("root")
);

我想做的事:

import React from "react";
import { render } from "react-dom";
import { types } from "mobx-state-tree";
import { observer } from "mobx-react";

const Todo = types.model({});

const eat = Todo.create({ name: "eat" });
render(
  <div>
    Eat TODO: {JSON.stringify(eat)}
  </div>,
  document.getElementById("root")
);

更多信息:

https://github.com/mobxjs/mobx-state-tree/issues/326#issuecomment-433906949

https://github.com/mobxjs/mobx-state-tree/pull/247

4

1 回答 1

2

这就是它在应用程序中的工作方式。它主要工作,只是添加和删除项目不会更新组件。

我想出了这个,它可以工作。它在沙箱中。这是一个进展中的工作。照原样,这不起作用,因为在初始化它们后不可能更改类型。

在https://egghead.io/lessons/react-create-dynamic-types-and-use-type-composition-to-extract-common-functionality的帮助下

https://codesandbox.io/s/m39mjomzwx

import React, { Component } from "react";
import { types } from "mobx-state-tree";
import { observer } from "mobx-react";
import { render } from "react-dom";

const ModelActions = types.model({}).actions(self => ({
  addToName: function addToName(string) {
    self.name = `${self.name} ${string}`;
  }
}));

function createModel(instance) {
  return types.compose(
    types.model(instance),
    ModelActions
  );
}

const TodoActions = types.model({}).actions(self => ({
  toggle: function toggle() {
    self.done = !self.done;
  }
}));

function createTodoModel(todo) {
  return types.compose(
    TodoActions,
    createModel(todo)
  );
}

function fetchUsers() {
  return Promise.resolve([{ id: 1234, name: "Jan" }]);
}

function fetchTodos() {
  return Promise.resolve([
    { id: 5, name: "eat", done: false },
    { id: 1, name: "drink" }
  ]);
}

function createDataStore(userData, todoData) {
  const User = createModel(userData[0]);
  const Todo = createTodoModel(todoData[0]);

  return types
    .model({
      users: types.map(User),
      todos: types.map(Todo)
    })
    .actions(self => {
      return {
        addUser(user) {
          self.users[user.id] = User.create(user);
        },
        removeUser(id) {
          self.users.delete(id);
        },
        addTodo(todo) {
          self.todos[todo.id] = Todo.create(todo);
        }
      };
    });
}

function makeStore([userData, todoData]) {
  const store = createDataStore(userData, todoData).create();

  function addData(add, data) {
    for (let i in data) {
      add(data[i]);
    }
  }

  addData(store.addTodo, todoData);
  addData(store.addUser, userData);

  return Promise.resolve(store);
}

const AppState = types.model({ selected: false }).actions(self => {
  return {
    select() {
      self.selected = !self.selected;
    }
  };
});

const appState = AppState.create();

let dataState = null;

// works
const ThingNode = observer(function ThingNode({ thing }) {
  return (
    <span>
      {JSON.stringify(thing)}
      <br />
    </span>
  );
});

function* getThingList(things) {
  for (let key in things) {
    if (Number(key)) {
      yield (
        <ThingNode key={key} thing={things[key]} />
      );
    }
  }
}

// does not add or remove items
const Child = observer(function Child({ state, store, ready }) {
  return (
    <div>
      Users:
      <br />
      {store ? [...getThingList(store.users)] : null}
      <br />
      Todos:
      <br />
      {store ? [...getThingList(store.todos)] : null}
      <br />
      Selected:
      <br />
      {JSON.stringify(state.selected)}
      <br />
      Ready:
      <br />
      {JSON.stringify(ready)}
    </div>
  );
});

@observer
class Parent extends Component {
  state = { ready: null };

  componentDidMount() {
    Promise.all([fetchUsers(), fetchTodos()])
      .then(makeStore)
      .then(state => {
        dataState = state;
        // this.setState({ ready: true });
        this.props.store.select();
      })
      .then(() => {
        // test some stuff
        dataState.addTodo({ id: 789, name: "eat a cake" });

        dataState.addUser({ id: 324, name: "Henk" });
        dataState.users[324].addToName("Klaassie");

        dataState.todos[1].addToName("haha");
        dataState.todos[5].toggle();

        setTimeout(() => {
          dataState.removeUser(1234);
          dataState.addTodo({ id: 90, name: "dinges" });
          dataState.todos[5].addToName("thing");
        }, 1000);

        setTimeout(() => {
          dataState.todos[789].addToName("hihi");
        }, 2000);

        setTimeout(() => {
          dataState.todos[90].addToName("twice");
        }, 4000);
      })
      .then(() => {
        this.setState({ ready: false });
      })
      .then(() => {
        // only now do the added / removed entries become visible
        setTimeout(() => this.setState({ ready: true }), 3000);
      });
  }

  render() {
    console.log("Parent", dataState);

    return (
      <Child
        store={dataState}
        state={this.props.store}
        ready={this.state.ready}
      />
    );
  }
}

render(<Parent store={appState} />, document.getElementById("root"));
于 2018-10-29T15:35:54.783 回答