2016-03-15 32 views
8

React + Reduxを試してみると、ネットワーク上でデータを取得するアクションを起動するコンポーネントがデータフェッチされます。React + Redux:コンポーネントが更新されない

import React from 'react'; 
import ReactDOM from 'react-dom'; 
import { Provider } from 'react-redux'; 
import { createStore, applyMiddleware } from 'redux'; 
import { Router, browserHistory } from 'react-router'; 
import reduxPromise from 'redux-promise'; 
import createLogger from 'redux-logger'; 

const logger = createLogger(); 

import routes from './routes'; 
import reducers from './reducers'; 

const createStoreWithMiddleware = applyMiddleware(reduxPromise, logger)(createStore); 

ReactDOM.render(
    <Provider store={createStoreWithMiddleware(reducers)}> 
    <Router history={browserHistory} routes={routes} /> 
    </Provider> 
    , document.querySelector('.container')); 

トップレベルのコンテナアプリケーション:

import React, {Component} from 'react'; 
import { bindActionCreators } from 'redux'; 
import { connect } from 'react-redux'; 
import * as Actions from '../actions'; 
import Header from '../components/header'; 
import Showcase from '../components/showcase'; 

function mapStateToProps(state) { 
    return { 
    resources: state.resources 
    } 
} 

function mapDispatchToProps(dispatch) { 
    return { 
    fetchResources:() => { 
     dispatch(Actions.fetchResources()); 
    } 
    } 
} 


class App extends Component { 

    render() { 
    console.log('props in App', this.props); 
    return (
     <div> 
     <Header/> 
     <Showcase 
      fetchResources={this.props.fetchResources} 
      resources={this.props.resources} 
     /> 
     </div> 
    ); 
    } 
} 

export default connect(
    mapStateToProps, 
    mapDispatchToProps 
)(App) 
アプリのエントリポイントとして

トップレベルのindex.js:ここ

は、私のコードの関連するビットです

アクションをトリガするコンポーネントは、マウントしようとしているときにデータの要求を送信し、取得したデータを表示するはずです。

import React, {Component} from 'react'; 
import {connect} from 'react-redux'; 

class Showcase extends Component { 
    constructor(props) { 
    super(props); 
    } 

    componentWillMount() { 
    this.props.fetchResources(); 
    } 

    render() { 
    console.log('resources', this.props); 
    return (
     <div> 
     This is showcase 
     </div> 
    ); 
    } 
} 

export default connect(state => ({resources: state.resources}))(Showcase) 

アクション作成者:フェッチアクションの

import * as types from '../constants/ActionTypes'; 
import axios from 'axios'; 

export function fetchResources() { 
    return { 
    type: types.FETCH_FIRST, 
    payload: axios.get('/sampledata/1.json') 
    } 
} 

リデューサー:

import * as types from '../constants/ActionTypes'; 

export default function resourcesReducer (state={}, action) { 
    switch (action.type) { 
    case types.FETCH_FIRST: 
     console.log('about to return', Object.assign (state, {resources: action.payload.data })) 
     return Object.assign (state, {resources: action.payload.data }); 
    default: 
     return state 
    } 
}; 

、最終的にはルート減速:だから、ここ

import { combineReducers } from 'redux'; 
import navigationReducer from './navigation-reducer'; 
import resourcesReducer from './resources-reducer'; 

const rootReducer = combineReducers({ 
    navigationReducer, 
    resourcesReducer 
}); 

export default rootReducer; 

は、私が観察していますものです。データを要求するアクションは正常にトリガーされ、要求が送信され、約束が解決されるとレデューサーはそれを受け取り、フェッチされたデータで状態を更新します。この時点で、トップレベルのAppコンポーネントとShowcaseコンポーネントが、ストアが更新されたことを検出して再レンダリングすることを期待しますが、コンソールには表示されません。

はまた、私はredux-loggerのコンソール出力で混乱しています:

enter image description here

は具体的に、私はstateがrootReducerから減速が含まれていることを確認するために驚いています - それが正しいかどうかはわかりません( Redux logger Github pageの例では、減速器のない状態を示しています)。直感的に私はprev stateが多かれ少なかれ空であると予想しているが、redux-loggerによって報告されたprev stateが同じresourcesReducerオブジェクトを含むことも驚くようである。

私が間違っていることを指摘し、どのように反応コンポーネントがstateの変更に応答するのか教えてください。

============================================== ====

を更新:

1)が正しく状態を減速するためにマップするようApp成分でmapStateToProps機能を変更:

function mapStateToProps(state) { 
    return { 
    resources: state.resourcesReducer 
    } 
} 

2)さらにまでresourcesを渡しますショーケースコンポーネント:

render() { 
    console.log('props in App', this.props); 
    return (
     <div> 
     <Header navigateActions={this.props.navigateActions}/> 
     React simple starter 
     <Showcase 
      fetchResources={this.props.fetchResources} 
      resources={this.props.resources} 
     /> 
     </div> 
    ); 

3)このオブジェクトの内部で実際に何があるか確認するために、それを文字列化して、画面上のresourcesを表示しようとすると:

render() { 
    console.log('resources', this.props); 
    return (
     <div> 
     This is showcase {JSON.stringify(this.props.resources)} 
     </div> 
    ); 
    } 

画面上でこれを参照してください:This is showcase {}。コンポーネントが再レンダリングされていないようです。ここで

は、Appの小道具はnext stateからの値で更新していることを示すコンソールのスクリーンショットです。それでも、そのコンポーネントを再レンダリングすることはありませんでした:

enter image description here

再び更新:そして、私のjavascript-FUも不良でした。 Object.assign (state, {resources: action.payload.data });私は実際に国家に突然変異を起こしていましたが、単純な議論の逆転が私の意図したものを達成することができたと思います。啓発のためにSOのthis discussionに感謝します。

+0

ルートレデューサーオブジェクトにキーを追加しようとしましたか? 'のconst rootReducer = combineReducers({ ナビゲーション:navigationReducer、 資源:resourcesReducer });' – anoop

答えて

6

私は状態は、それがどのように動作するかこれはrootReducer

から減速が含まれていることを確認するために驚いています。 combineReducers()を詳しく見てください。

const rootReducer = combineReducers({ 
    navigationReducer, 
    resourcesReducer 
}); 

パラメータのリストではないことを認識してください。それは単一のオブジェクトパラメータです。

var rootReducer = combineReducers({ 
    navigationReducer: navigationReducer, 
    resourcesReducer: resourcesReducer 
}); 

resourcesReducer()関数によって返された状態にresourcesReducerキーポイント:おそらくそれはES5構文で明確です。つまり、resourcesReducer()内のstate変数は、状態全体の一部に過ぎません。

connect()に渡された関数は、引数として全体の状態を取ります。あなたの実際の外観は次のとおりです。

export default connect(state => ({ 
    resources: state.resourcesReducer.resources 
}))(Showcase); 
+0

ありがとうございました。あなたのコメントは、(私の元の質問の最新のセクションを参照してください)状態とリデューサー(とcombineReducers)の間の関係が何であるか、私は自分のコードを更新した後でも、それが明確に作られた状態の更新は、コンポーネントの再描画にはつながりません。私は今、自分の 'App'コンポーネントだけをストアに登録し、' {resources:state.resourcesReducer} 'を返すように' mapStateToProps'関数を変更しました。状態の更新と 'App'の小道具がこの変更を反映していることがわかりますが、これによってApp(またはShowcase)が再レンダリングされることはありません。私は何が欠けていますか? – azangru

+1

さて、私は何が起こったのか理解しています。私の 'Object.assign'も間違っていました。私が本当に必要としていたのは、新しいオブジェクトを返すことでした(例えば 'return Object.assign({resources:action .payload.data}、state) ')。愚かな私。しかし、一般的な間違いだと思われる。私が逃したので、非常によく似た投稿があります:http://stackoverflow.com/questions/33140008/react-redux-store-updates-but-react-does-not – azangru