为什么在使用redux-state-sync时即使状态已更改,redux @select也无法工作? [英] Why redux @select does not work even though the state is changed when using redux-state-sync?
问题描述
编辑-如果我将redux-state-sync配置为使用localstorage,那么这一切都可行.我创建了一个存储库 https://bitbucket.org/em-aitch/sync -app/src/master/,其中包含工作代码示例.如果广播频道类型(app.component.ts:76)从'localstorage'更改为'native',则绑定(@select和{{property}}都不再起作用!
EDIT - This all works if I configure redux-state-sync to use localstorage. I made a repository https://bitbucket.org/em-aitch/sync-app/src/master/ that contains example of working code. If broadcastchannel type (app.component.ts : 76) is changed from 'localstorage' to 'native' the bindings (both @select and {{ property }} don't work anymore!
EDIT2-问题如何找出破坏Angular的方法绑定?回答这个问题
EDIT2 - Question How to find out what breaks Angular binding? answers this question
我已使用以下所述的 redux-state-sync 进行设置. Redux状态更改已同步到其他浏览器窗口,但@select不起作用.
I have setup using redux-state-sync described below. The redux state change is synced to other browser window but @select does not work.
当我在一个窗口中登录时,会出现app-nav-menu,因为ngIf评估为true.同样,两个预订都将写入控制台:
When I log in in one window app-nav-menu appears because ngIf evaluates true. Also both subsriptions write to console:
new login state = true app.component.ts:20
subsribed to local observable : true app.component.ts:24
但是,即使在另一个窗口中完成的登录状态更改已在那里同步,其他浏览器窗口也无法以相同的方式工作.控制台输出是相同的:
However other browser window does not work the same way even though the login state change done in the other window is synced there. Console ouput is the same:
new login state = true app.component.ts:20
subsribed to local observable : true app.component.ts:24
但是,问题是没有出现app-nav-menu.下面首先是与此代码直接相关的代码,最后是redux定义.
The problem however is that the app-nav-menu DOES NOT appear. Below first is the code directly related to this and in the end the redux definitions.
app.component.html
app.component.html
<body>
<app-nav-menu *ngIf="(isLoggedIn | async)"></app-nav-menu>
<div class="container">
<router-outlet></router-outlet>
</div>
</body>
app.component.ts
app.component.ts
export class AppComponent {
title = 'app';
@select((state: IApplicationState) => state.login.isLoggedIn) isLoggedIn: Observable<boolean>;
subscription;
constructor(private ngRedux: NgRedux<IApplicationState>) {
this.subscription = this.ngRedux.select<ILoginState>('login')
.subscribe(newState => {
console.log('new login state = ' + newState.isLoggedIn);
});
this.isLoggedIn.subscribe(newState =>
console.log('subsribed to local observable : ' + newState));
}
}
app.module.ts
app.module.ts
import { createStateSyncMiddleware, initStateWithPrevTab } from 'redux-state-sync';
import { Store, createStore, applyMiddleware } from 'redux';
export const store: Store<IApplicationState> = createStore(
rootReducer,
applyMiddleware(createStateSyncMiddleware())
);
export class AppModule {
constructor(ngRedux: NgRedux<any>) {
ngRedux.provideStore(store);
initStateWithPrevTab(store);
}
}
store/index.ts
store/index.ts
import { combineReducers } from 'redux'
import { ILoginState, loginReducer } from './login'
import { withReduxStateSync } from 'redux-state-sync'
export interface IApplicationState {
login: ILoginState;
}
export const INITIAL_STATE : IApplicationState = {
login : { isLoggedIn: false, tokenInfo : null }
}
const appReducer = combineReducers<IApplicationState>({
login: loginReducer
})
export const rootReducer = withReduxStateSync(appReducer);
就像我在顶部的编辑中说的那样.如果我将其配置为使用localstorage,则此方法有效:
Like I said in edit in the top. This works if I configure this to use localstorage:
applyMiddleware(createStateSyncMiddleware(
{ broadcastChannelOption: { type: 'localstorage' } })));
推荐答案
如果状态已经同步,则可能不是redux-state-sync问题,但是,我想帮助您解决问题,我对Angular和@select的了解有限.
If the state is already in sync, likely the problem is not in redux-state-sync, I would like to help you to solve the problem, however, I have limited knowledge of Angular and @select.
但是我可以与您分享Redux-state-sync如何在浏览器标签之间同步数据.
But I can share with you that how redux-state-sync works to sync the data across the browser tabs.
- 初始化期间将触发三个动作.
const getIniteState = () => ({ type: GET_INIT_STATE });
const sendIniteState = () => ({ type: SEND_INIT_STATE });
const receiveIniteState = state => ({ type: RECEIVE_INIT_STATE, payload: state });
-
在第一个选项卡之后打开的选项卡将把GET_INIT_STATE操作分派到另一个选项卡的存储中,一旦他们收到此操作,它们将分派SEND_INIT_STATE以及现有状态.同时,您最后打开的标签页会收到此SEND_INIT_STATE事件以及其他标签页的整个状态,并使用该状态触发RECEIVE_INIT_STATE.
The tabs that opened after the first tab will dispatch GET_INIT_STATE action to the other tab's store, once they received this action, they will dispatch SEND_INIT_STATE along with there existing state. At the same time your last opened tab will receive this SEND_INIT_STATE event along with the other tab's entire state and triggers RECEIVE_INIT_STATE with the state.
基本上,withReduxStateSync将侦听RECEIVE_INIT_STATE操作,并将整个状态替换为该操作的有效负载.
Basically, withReduxStateSync will listen on RECEIVE_INIT_STATE action, and replace the entire state with this action's payload.
export const withReduxStateSync = appReducer =>
((state, action) => {
let initState = state;
if (action.type === RECEIVE_INIT_STATE) {
initState = action.payload;
}
return appReducer(initState, action);
});
- 从您的应用程序分派的所有其他操作将在所有打开的浏览器选项卡中分派,并带有确切的操作类型和有效负载.
据我所知,您面临的问题可能是可观察到的问题,即没有检测到状态的任何变化,因此不会触发更新.
From what I see, the problem that you are facing is probably the observable is not detecting any changes on the state, so that it doesn't trigger the update.
希望这会有所帮助,对不起,我无法为您提供更多有用的建议.如果您需要我提供更多信息,请告诉我,如果您解决了此问题,也请告诉我. ;-)
Hope this helps, sorry that I couldn't give you more useful suggestions. Let me know if you need more information from me and if you solved this problem please let me know as well. ;-)
这篇关于为什么在使用redux-state-sync时即使状态已更改,redux @select也无法工作?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!