这就是它在应用程序中的工作方式。它主要工作,只是添加和删除项目不会更新组件。
我想出了这个,它可以工作。它在沙箱中。这是一个进展中的工作。照原样,这不起作用,因为在初始化它们后不可能更改类型。
在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"));