angular2/rxjs/redux 重新实现 - 路由更改与 observable 混淆
angular2/rxjs/redux reimplementation - route change messing with observable
我正在尝试在 angular2 应用程序的 rxjs 中对 redux 进行基本的重新实现。
此时基本上只是我在互联网上找到的一些东西拼接在一起,this plunker for angular DI, this for file structure, this for combineReducers and lastly this for "redux in rxjs"。
我遇到了几个问题,但这是目前最大的问题:
https://www.youtube.com/watch?v=xXau87UmqOs
发生了什么:
- 我有两个组件,
index
和 todos
每个组件都有一条路线
- 在索引中我只显示待办事项列表
- 在待办事项中我可以删除和添加新的待办事项
- 当我在不添加新待办事项或删除待办事项的情况下切换路线时,一切正常
- 当我添加或删除一个待办事项时,它仍然有效,新的待办事项被附加,旧的待办事项被删除,
console.log
中的数据看起来很好
- 当我在添加或删除待办事项后转到不同的路线时,observable 成为我调用的最后一个 redux 操作,例如
Object {type: "DELETE_TODO", id: 1}
而不是待办事项数组
这是我在 console.log
中描述的内容(也可以在 youtube 视频中看到)
---- index loaded ----
index.js:33 map in index: Object {todos: Array[3]}
index.js:35 resp in index: Object {todos: Array[3]}
index.js:38 ---- index destroyed ----
todos.js:31 ---- todos loaded ----
todos.js:33 map in todos: Object {todos: Array[3]}
todos.js:35 resp in todos: Object {todos: Array[3]}
todos.js:45 ---- todos destroyed ----
index.js:30 ---- index loaded ----
index.js:33 map in index: Object {todos: Array[3]}
index.js:35 resp in index: Object {todos: Array[3]}
index.js:38 ---- index destroyed ----
todos.js:31 ---- todos loaded ----
todos.js:33 map in todos: Object {todos: Array[3]}
todos.js:35 resp in todos: Object {todos: Array[3]}
NgStore.js:49 Object {type: "DELETE_TODO", id: 1}
todos.js:33 map in todos: Object {todos: Array[2]}
todos.js:35 resp in todos: Object {todos: Array[2]}
todos.js:45 ---- todos destroyed ----
index.js:30 ---- index loaded ----
index.js:33 map in index: Object {type: "DELETE_TODO", id: 1}
index.js:35 resp in index: Object {type: "DELETE_TODO", id: 1}
知道什么会导致 observable 在路由改变时发生改变吗?
这是 repo https://github.com/fxck/ng2-rx-redux 它使用最新的 alpha(46)
您不需要在 rxjs
中实现 redux
,因为它已经在那里实现了。 Observable::scan(accumulator, [seed]) operator does exactly the same what redux
does. Here's a simplified example (see this plunk):
// store.js
import BehaviorSubject from '@reactivex/rxjs/dist/cjs/subjects/BehaviorSubject';
import reducer from './reducer';
export default new BehaviorSubject().scan(reducer, 0)
// reducer.js
export default function(state, action) {
switch (action && action.type) {
case 'INCREMENT':
return state + 1;
case 'DECREMENT':
return state - 1;
default:
return state;
}
}
// app.js
import {Component} from 'angular2/angular2'
import store from './store';
@Component({
selector: 'my-app',
template: `
<h2>{{ value }}</h2>
<button (click)="increment()">Increment</button>
<button (click)="decrement()">Decrement</button>
`
})
export class App {
constructor() {
store.subscribe(value => this.value = value);
}
increment() { store.next({ type: 'INCREMENT' }) }
decrement() { store.next({ type: 'DECREMENT' }) }
}
嗯,当然你可以重新发明轮子(至少只是为了好玩)。
暗中拍摄。路线更改是视图状态的更改。我敢打赌 angular2 会重新创建或更新您在路由器中配置的组件。您所描述的是:
- 路线改变但模型没有改变:OK
- 待办事项模型中的路线更改和状态更改会给您错误的结果。
我在 Angular 中的经验是零,但从我读到的内容来看,我的直觉是:
- 如果状态没有变化,路由器不会更新组件(不需要,因为它们只依赖于没有变化的状态,对吧?)
- 如果状态发生变化,则路由器会要求更新受影响的组件。因为你取回了最后一个 redux 动作,并且你使用了一个行为主题,我盲目猜测可能是你一直保持主题活跃,并在路由更改时重新订阅,当你重新订阅时,你取回了最后一个价值(这是行为主体根据规范所做的)。
这完全是一团糟,但你应该尝试在这些线上进行测试,至少要排除这种可能性。
您使用 RxJS
API 不正确。要修复您的代码,您应该做接下来的两件事:
- 将初始状态设置为
scan
运算符。
// services/NgStore.ts
this._subject = new BehaviorSubject().scan(rootReducer, initialState);
- 更改
switch
语句中的条件以检查 action
是否为空(例如 === undefined
):
// reducers/todo.ts
export const todos = (state = [], action) => {
switch(action && action.type) {
// ...
}
};
PS 对于不知道 redux 已经在 RxJS 中实现的人,我不会删除我的第一个答案。
我正在尝试在 angular2 应用程序的 rxjs 中对 redux 进行基本的重新实现。
此时基本上只是我在互联网上找到的一些东西拼接在一起,this plunker for angular DI, this for file structure, this for combineReducers and lastly this for "redux in rxjs"。
我遇到了几个问题,但这是目前最大的问题: https://www.youtube.com/watch?v=xXau87UmqOs
发生了什么:
- 我有两个组件,
index
和todos
每个组件都有一条路线 - 在索引中我只显示待办事项列表
- 在待办事项中我可以删除和添加新的待办事项
- 当我在不添加新待办事项或删除待办事项的情况下切换路线时,一切正常
- 当我添加或删除一个待办事项时,它仍然有效,新的待办事项被附加,旧的待办事项被删除,
console.log
中的数据看起来很好 - 当我在添加或删除待办事项后转到不同的路线时,observable 成为我调用的最后一个 redux 操作,例如
Object {type: "DELETE_TODO", id: 1}
而不是待办事项数组
这是我在 console.log
中描述的内容(也可以在 youtube 视频中看到)
---- index loaded ----
index.js:33 map in index: Object {todos: Array[3]}
index.js:35 resp in index: Object {todos: Array[3]}
index.js:38 ---- index destroyed ----
todos.js:31 ---- todos loaded ----
todos.js:33 map in todos: Object {todos: Array[3]}
todos.js:35 resp in todos: Object {todos: Array[3]}
todos.js:45 ---- todos destroyed ----
index.js:30 ---- index loaded ----
index.js:33 map in index: Object {todos: Array[3]}
index.js:35 resp in index: Object {todos: Array[3]}
index.js:38 ---- index destroyed ----
todos.js:31 ---- todos loaded ----
todos.js:33 map in todos: Object {todos: Array[3]}
todos.js:35 resp in todos: Object {todos: Array[3]}
NgStore.js:49 Object {type: "DELETE_TODO", id: 1}
todos.js:33 map in todos: Object {todos: Array[2]}
todos.js:35 resp in todos: Object {todos: Array[2]}
todos.js:45 ---- todos destroyed ----
index.js:30 ---- index loaded ----
index.js:33 map in index: Object {type: "DELETE_TODO", id: 1}
index.js:35 resp in index: Object {type: "DELETE_TODO", id: 1}
知道什么会导致 observable 在路由改变时发生改变吗?
这是 repo https://github.com/fxck/ng2-rx-redux 它使用最新的 alpha(46)
您不需要在 rxjs
中实现 redux
,因为它已经在那里实现了。 Observable::scan(accumulator, [seed]) operator does exactly the same what redux
does. Here's a simplified example (see this plunk):
// store.js
import BehaviorSubject from '@reactivex/rxjs/dist/cjs/subjects/BehaviorSubject';
import reducer from './reducer';
export default new BehaviorSubject().scan(reducer, 0)
// reducer.js
export default function(state, action) {
switch (action && action.type) {
case 'INCREMENT':
return state + 1;
case 'DECREMENT':
return state - 1;
default:
return state;
}
}
// app.js
import {Component} from 'angular2/angular2'
import store from './store';
@Component({
selector: 'my-app',
template: `
<h2>{{ value }}</h2>
<button (click)="increment()">Increment</button>
<button (click)="decrement()">Decrement</button>
`
})
export class App {
constructor() {
store.subscribe(value => this.value = value);
}
increment() { store.next({ type: 'INCREMENT' }) }
decrement() { store.next({ type: 'DECREMENT' }) }
}
嗯,当然你可以重新发明轮子(至少只是为了好玩)。
暗中拍摄。路线更改是视图状态的更改。我敢打赌 angular2 会重新创建或更新您在路由器中配置的组件。您所描述的是:
- 路线改变但模型没有改变:OK
- 待办事项模型中的路线更改和状态更改会给您错误的结果。
我在 Angular 中的经验是零,但从我读到的内容来看,我的直觉是:
- 如果状态没有变化,路由器不会更新组件(不需要,因为它们只依赖于没有变化的状态,对吧?)
- 如果状态发生变化,则路由器会要求更新受影响的组件。因为你取回了最后一个 redux 动作,并且你使用了一个行为主题,我盲目猜测可能是你一直保持主题活跃,并在路由更改时重新订阅,当你重新订阅时,你取回了最后一个价值(这是行为主体根据规范所做的)。
这完全是一团糟,但你应该尝试在这些线上进行测试,至少要排除这种可能性。
您使用 RxJS
API 不正确。要修复您的代码,您应该做接下来的两件事:
- 将初始状态设置为
scan
运算符。
// services/NgStore.ts
this._subject = new BehaviorSubject().scan(rootReducer, initialState);
- 更改
switch
语句中的条件以检查action
是否为空(例如 ===undefined
):
// reducers/todo.ts
export const todos = (state = [], action) => {
switch(action && action.type) {
// ...
}
};
PS 对于不知道 redux 已经在 RxJS 中实现的人,我不会删除我的第一个答案。