当一个动作被调度到映射到该组件的reducer时,我遇到了在我的react组件上更新我的props属性的问题 . 我将在显示代码的过程中解释 .
首先,我试图在我的反应组件之外调度动作(从电子菜单项点击发出的调度) .
这是调度操作的菜单服务功能 . 如果我们在发送后执行 console.log(store.getState())
,我们会在商店状态中看到正确的消息:
dispatchMessage(): void {
let message = messageService.getMessage();
let store = StoreProvider.getInstance().store;
store.dispatch(loadMessage(message));
}
注意StoreProvider获取Redux存储的实例,这是因为代码超出了React组件的范围,这就是StoreProvider.ts:
import { createStore } from 'redux';
import allReducers from '../reducers/index';
export default class StoreProvider {
private static _instance: StoreProvider;
store: any = null;
constructor() {
this.store = createStore(
allReducers
);
}
public static getInstance(): StoreProvider {
return StoreProvider._instance || (StoreProvider._instance = new StoreProvider());
}
}
这是我的index.tsx文件,我在其中引导App组件并使用相同的商店提供程序加载商店(这将填充StoreProvider的新实例,其中构造函数将设置我稍后可以在菜单项中访问的商店点击):
import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import allReducers from './reducers/index';
import App from './app';
import StoreProvider from './providers/store-provider';
const bootstrapperElement: HTMLElement = document.getElementById('app') as HTMLElement;
const store = StoreProvider.getInstance().store;
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
bootstrapperElement);
好的,这就是事情如何连接到动作发送的位置 . 因此,当我在菜单服务功能中调度我的动作时,它正在调用此动作:
export const loadMessage = (message: any) => {
return {
type: 'MESSAGE_LOADED',
payload: message
};
};
一旦调度动作,它就被这个减速器拾取 . 注意 console.log(action.payload)
,此时它将正确记录从菜单服务调度的消息,我可以看到预期的内容,到目前为止似乎正在工作 .
export default (state: any = null, action: any) => {
switch (action.type) {
case 'MESSAGE_LOADED':
console.log(action.payload);
return action.payload;
default:
return state;
}
};
这是将该状态映射到props的组件:
import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
class SideMenu extends Component<any> {
render() {
return (
<div>
<h2 onClick={ () => console.log(this.props.fileExplorer)}>Test</h2>
</div>
);
}
}
const mapStateToProps = (state: any) => {
return {
fileExplorer: state.fileExplorer
};
};
export default connect<any>(mapStateToProps, {})(SideMenu);
因此当我单击带有'TEST'文本的h2元素时,我总是得到null,这是最初传递到正在拾取该消息的reducer的默认值(尽管上面我们知道了console.log中的当从菜单服务调度动作时,reducer确实打印了正确的值 .
这也是我正在添加到商店的减速器:
import { combineReducers } from 'redux';
import FileExplorerReducer from './file-explorer';
const allReducers = combineReducers({
fileExplorer: FileExplorerReducer
});
export default allReducers;
我们将非常感谢您对此问题的任何帮助 . 我相信在这一刻我倾向于它是StoreProvider的一个问题,可能有两个单独的商店实例?不太确定为什么组件this.props.fileExplorer总是为null,即使reducer返回action.payload并且更新了商店的fileExplorer状态(至少在发送后检查菜单服务) .
Changes to answer the above question according to the accepted answer:
因此,不得不允许IPC(进程间通信),我们必须在菜单服务中从BrowserWindow.webContents.send()发布消息,如下所示:
let message = let message = messageService.getMessage();
BrowserWindow.getFocusedWindow().webContents.send('dispatch-action', { payload: { message});
然后在Store Provider中,我在构造函数中添加了订阅者,因此商店实例可以在渲染器进程中接收从主进程发布的消息,如下所示:
import { ipcRenderer } from 'electron';
export default class StoreProvider {
private static _instance: StoreProvider;
store: any = null;
constructor() {
this.store = createStore(
allReducers
);
ipcRenderer.on('dispatch-action', (event: any, arg: any) => {
this.store.dispatch(loadMessage(arg.payload));
});
}
public static getInstance(): StoreProvider {
return StoreProvider._instance || (StoreProvider._instance = new StoreProvider());
}
}
1 回答
我不能完全肯定,但根据你的描述说你试图在Electron的菜单事件上执行,我想建议检查你正在调度菜单事件的过程 . 如果它不是渲染您的react组件的渲染器进程,您可能会看到每个不同的进程都有隔离的存储状态,可能需要存储用于redux的同步中间件或者调用IPC进入渲染器进程,然后让渲染器直接为渲染器端redux存储调度操作 .