2015-09-25 131 views
3

我使用Redux作爲Flux替代方案,而React作爲視圖層。我的應用程序的ReactReduxreact-reduxconnect()方法綁定。 運行應用程序時,它會在組件掛載並且redux返回正確的狀態時調度該操作。但redux-logger登錄到商店用新狀態更新的控制檯中,在組件中檢查this.props.session時它仍顯示舊狀態。我猜測我沒有正確使用connect方法,但是我也無法定義它的問題。有人有一個想法是怎麼回事?React-redux,連接功能不會更新新數據的狀態

容器/應用

'use strict'; 

import React from 'react'; 
import {connect} from 'react-redux'; 
import {fetchUserSession} from 'actions/SessionActions'; 

class App extends React.Component { 
    constructor(props) { 
    super(props); 
    } 
    componentWillMount() { 
    const {dispatch, session} = this.props; 
    dispatch(fetchUserSession()); 
    console.log(session); 
    // logs: 
    // Object {currentUserId: null, errorMessage: null, isSessionValid: null} 

    // store is bound to window, and the initial state is ImmutabeJS object 
    console.log(window.store.getState().session.toJS()); 
    // logs: 
    // Object {currentUserId: null, errorMessage: null, isSessionValid: false} 
    // as you might noticed the isSessionValid is changed to false 
    } 

    render() { 
    // html here 
    } 
} 

function mapStateToProps(state){ 
    return { 
    session: state.session.toJS() 
    }; 
} 

export default connect(mapStateToProps)(App); 

動作/ Actions.js

'use strict'; 

import fetch from 'isomorphic-fetch'; 

export const SESSION_REQUEST = 'SESSION_REQUEST'; 
export const SESSION_SUCCESS = 'SESSION_SUCCESS'; 

export function requestSession() { 
    return { 
    type: SESSION_REQUEST 
    }; 
} 

export function receiveSession(user) { 
    return { 
    type: SESSION_REQUEST, 
    user 
    }; 
} 

export function fetchUserSession() { 
    return dispatch => { 
    dispatch(requestSession()); 
    return fetch(`http://localhost:5000/session`) 
     .then((response) => { 
     if (response.status === 404) { 
      dispatch(raiseSessionFailure(response)); 
     } 
     return response.json(); 
     }) 
     .then(userData => dispatch(receiveSession(userData))); 
    }; 
} 

減速器/ SessionReducer.js

'use strict'; 
import {fromJS} from 'immutable'; 

// UPDATE!!! 
// here is the initial state 
const initialState = fromJS({ 
    currentUserId: null, 
    errorMessage: null, 
    isSessionValid: null 
}); 

function sessionReducer(state = initialState, action) { 
    switch (action.type) { 
    case 'SESSION_REQUEST': 
     return state.update('isSessionValid',() => false); 
    case 'SESSION_SUCCESS': 
     console.log('Reducer: SESSION_SUCCESS'); 
     return state; 
    case 'SESSION_FAILURE': 
     console.log('Reducer: SESSION_FAILURE'); 
     return state; 
    default: 
     return state; 
    } 
} 

export default sessionReducer; 

級減速器/ RootReducer

'use strict'; 

import {combineReducers} from 'redux'; 
import sessionReducer from 'reducers/SessionReducer'; 

const rootReducer = combineReducers({ 
    session: sessionReducer 
}); 

export default rootReducer; 
+1

你能顯示你的狀態是什麼樣子嗎?我認爲,因爲你沒有合併減速器,它看起來就像'initialState',你是否也可以包含這個呢? – Clarkie

+0

嗨@Clarkie我更新了減速機,並把我如何結合減速機 – Max

+1

你有沒有嘗試讓它在沒有使用immutableJS庫的情況下工作?我只用過[immutability helpers](https://facebook.github.io/react/docs/update.html)中的redux反應 – Clarkie

回答

5

問題出在session變量從props和商店中記錄的方式。當您將動作分派到更新狀態時,它會同步更新商店,這就是爲什麼您在直接登錄時發現商店已更新的原因。然而,react-redux將無法更新道具,直到componentWillMount的調用完成,並且React有機會追趕並重新渲染具有新狀態的組件。如果您在componentWillMount中發送操作並在稍後記錄session prop,則會看到它已更改爲反映該操作。

0

看起來你不行動處理器在減速改變狀態。只有casereturn state以外的代碼表示state.update('isSessionValid',() => false) - 它返回的是什麼?如果它與之前的狀態是相同的對象,那麼由於不可變約定,redux不會改變任何內容。

+0

'state'是'ImmutableJs'對象,'update'是'Map'類的方法。這裏是[完整文檔](https://facebook.github.io/immutable-js/docs/#/Map/update)。基本上,'update'函數將返回新的'Map'對象與'isSessionValid'到假,最初它是'null' – Max

+0

@Max,並且在使用此字段的客戶端代碼中,您是否明確區分了null和false?因爲JavaScript中的'compute to false',這看起來像可能的麻煩 –