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

Javascript Redux reducer未从React组件外部调度更新React组件中的prop值,javascript,reactjs,typescript,redux,react-redux,Javascript,Reactjs,Typescript,Redux,React Redux,当一个动作被分派到映射到该组件的减速器时,我在更新react组件上的props属性时遇到问题。我将在显示代码的过程中进行解释 因此,首先,我尝试在我的react组件之外分派操作(从Electron菜单项单击激发分派) 这是分派操作的菜单服务功能。如果在分派后执行console.log(store.getState()),我们将正确地看到处于存储状态的消息: dispatchMessage(): void { let message = messageService.getMessage(

当一个动作被分派到映射到该组件的减速器时,我在更新react组件上的props属性时遇到问题。我将在显示代码的过程中进行解释

因此,首先,我尝试在我的react组件之外分派操作(从Electron菜单项单击激发分派)

这是分派操作的菜单服务功能。如果在分派后执行
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文件,我在其中引导应用程序组件并使用相同的存储提供程序加载存储(这将填充存储提供程序的新实例,构造函数将在其中设置我稍后可以在菜单项单击中访问的存储):

一旦动作被分派,它就会被这个减速机拾取。请注意
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;
    }
};
这是将该状态映射到道具的组件:

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);
在此问题上的任何协助都将不胜感激。我相信在这一刻,我倾向于这是一个与商店供应商的问题,可能有2个商店的独立实例?不太清楚为什么组件this.props.fileExplorer总是空的,即使reducer返回action.payload并且存储的fileExplorer状态已更新(至少在分派后通过检查菜单服务)

根据接受的答案更改以上问题的答案:

因此,为了允许IPC(进程间通信),我们必须在菜单服务中发布来自BrowserWindow.WebContent.send()的消息,如下所示:

let message = let message = messageService.getMessage();
BrowserWindow.getFocusedWindow().webContents.send('dispatch-action', { payload: { message});
然后在Store Provider中,我在构造函数中添加了订阅者,以便Store的实例可以接收从渲染器进程中的主进程发布的消息,如下所示:

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());
    }
}

我不能完全确定,但根据您的描述,您正在尝试执行Electron的菜单事件,我建议您检查发送菜单事件的进程。如果不是承载react组件的渲染器进程,您可能会看到每个不同的进程都有独立的存储状态,可能需要用于redux的存储同步中间件,或者在渲染器进程中调用IPC,然后让渲染器直接为渲染器端redux存储分派操作。

在非react组件中调用
store.dispatch()
时,我也会遇到同样的问题。我不确定这是否是正确的方法,但我可以通过将存储传递到组件并从组件中修复它,将接收到的存储传递给非react组件,然后使用这个接收到的存储来分派我的操作

index.js

<Provider store={configstore}>
    <BrowserRouter>
        <App>
            <Switch>

                <Route exact path="/addinvoice" component={authGuard(AddInvoice)} storeHack={configStore} />
            </Switch>
        </App>
    </BrowserRouter>
</Provider>
参考:
}

尝试将您的状态记录到侧菜单组件MapStateTops中,以确保您拥有正确的state@cdoshi刚刚做了那个lol。它给了我一个属性为“fileExplorer:null”的对象。当然,我觉得这个商店有点搞笑。当这个商店是由一个随机数创建的时候,我刚刚为fileExplorer添加了一个默认值。在这个实例上,当这个商店加载到提供者中时,我得到了52个,当我在菜单服务中得到了这个商店的一个实例时,我得到了75个。因此,它被确认有两个不同的商店实例,只需找出如何保持在一个。我以为我在实现一个要使用的单例。从上面的代码来看,似乎没有多个存储。对不起,我帮不上什么忙。所有的好人,感谢你抽出时间来看我!
let message = let message = messageService.getMessage();
BrowserWindow.getFocusedWindow().webContents.send('dispatch-action', { payload: { message});
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());
    }
}
<Provider store={configstore}>
    <BrowserRouter>
        <App>
            <Switch>

                <Route exact path="/addinvoice" component={authGuard(AddInvoice)} storeHack={configStore} />
            </Switch>
        </App>
    </BrowserRouter>
</Provider>
class AddInvoice extends Component {
constructor(props){
    super(props)
    this.state={
        store:props
    }
    console.log("store received in add invoice is",this.state) 
}
render(){
 return(
    //pass this.state.store to the non react-component
    //and use the received parameter.dispatch(actionName) in ur non-react component and u ready to go
  )