首页 文章

Redux reducer不从React组件外部的调度更新React组件中的prop值

提问于
浏览
0

当一个动作被调度到映射到该组件的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 回答

  • 1

    我不能完全肯定,但根据你的描述说你试图在Electron的菜单事件上执行,我想建议检查你正在调度菜单事件的过程 . 如果它不是渲染您的react组件的渲染器进程,您可能会看到每个不同的进程都有隔离的存储状态,可能需要存储用于redux的同步中间件或者调用IPC进入渲染器进程,然后让渲染器直接为渲染器端redux存储调度操作 .

相关问题