2017-12-23 8 views
0

アクションがそのコンポーネントにマップされているレデューサーにディスパッチされたときに、反応コンポーネントのmypropsプロパティを更新する際に問題があります。私は途中でコードを見て説明します。Redux reducerがReactコンポーネントのprop値を更新していません。Reactコンポーネントの外へのディスパッチから。

最初に、私は反応コンポーネントの外にアクションをディスパッチしようとしています(Electronメニューアイテムのクリックから発射されました)。

これはアクションをディスパッチするメニューサービス機能です。コードが範囲外であるため、Reduxのストアのインスタンスを取得StoreProviderが、これが行われている

dispatchMessage(): void { 
    let message = messageService.getMessage(); 
    let store = StoreProvider.getInstance().store; 
    store.dispatch(loadMessage(message)); 
} 

お知らせ:私たちは発送後console.log(store.getState())を行うとしたら、私たちは正しくストアの状態のメッセージが表示されます

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ファイルである(これはの新しいインスタンスを移入します:リアクトのコンポーネントで、これはStoreProvider.tsです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); 

[OK]これは、アクションがディスパッチされているポイントまでのものです。私は、メニューのサービス機能で自分の行動を派遣するときだから、それはこのアクションを呼び出している:

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

これは小道具にその状態をマッピングしているコンポーネントである:私はテキスト「TEST」とH2要素をクリックしたときに

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

だから、私は常にデフォルトである、nullを取得していますそのメッセージをピックアップしている減速機に最初に渡された値(メニューサービスからアクションが送出されたときに減速機のconsole.logが実際に正しい値を出力していることはわかっています)。

また、これは私が店に追加してい私のレデューサーです:

import { combineReducers } from 'redux'; 

import FileExplorerReducer from './file-explorer'; 

const allReducers = combineReducers({ 
    fileExplorer: FileExplorerReducer 
}); 

export default allReducers; 

この問題でどのような援助を大幅に理解されるであろう。私はこの時点で、StoreProviderの問題であることに賛成し、店舗の2つの別々のインスタンスが存在する可能性があると考えていますか?レジューサーがaction.payloadを返しても、(少なくともディスパッチ後にメニューサービスをチェックすることで)ストアのfileExplorer状態が更新されても、なぜthis.props.fileExplorerコンポーネントが常にnullであるのかは不明です。

変更は受け入れ答えに応じて上記の質問に答えるために:

だからIPC(プロセス間通信)を可能にした、我々はBrowserWindow.webContentsからのメッセージを公開しなければなりませんでした。そのようなメニューのサービスに()を送る:ストアのインスタンスはレンダラープロセスにおける主要なプロセスから発行されたメッセージを受け取ることができるように

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

あなたのSidemenuコンポーネントのmapstatetopropsにあなたの状態を記録してみてください。あなたが正しい状態になっていることを確認してください。 – cdoshi

+0

@cdoshiはちょうどその笑いました。それは私にプロパティ "fileExplorer:null"を持つオブジェクトを与えています。確かに面白い何かが店で起こっていることを確信している – Shawn

+0

ストアがプロバイダにロードされているインスタンスで、ストアが乱数の作成時にfileExplorerのデフォルト値を追加しただけで、私は52を得て、私は75を持っているメニューサービスの店のインスタンス。それは店の2つの別々のインスタンスがあることが確認されたので、ちょうどそれを1つに保つ方法を理解する必要があります。私は使用するシングルトンを実装していたと思った。 – Shawn

答えて

1

私は完全には特定ができますが、電子のメニューイベントで実行しようとしていると言ってあなたの説明に基づいてすることはできません、私はあなたがメニューイベントを送出していたプロセスをチェックすることをお勧めしたいと思います。あなたが反応コンポーネントをホストするレンダラープロセスでない場合、それぞれの異なるプロセスがストア状態を分離しているのを見るかもしれませんし、reduxのためにストア同期ミドルウェアを必要とするか、またはIPCをレンダラープロセスに呼び出すか、レンダラーがレンダー側レデックスストアのアクションを直接ディスパッチする。

関連する問題