2017-04-05 177 views
1

我正在使用Recompose設置React Native中的用戶登錄屏幕,其中包含單獨的動作和reducer文件,但我的reducer永遠不會被調用。目前,還只是觸發doUserLogin()重新合成處理登錄按鈕:React Native重構動作不觸發reducer

loginScreen.js

import React from 'react'; 
import { Button, Text, View } from 'react-native'; 
import { connect } from 'react-redux'; 
import { withHandlers, compose } from 'recompose'; 
import { loginUser } from './user/userActions'; 

const LoginScreen = ({ user, doUserLogin }) => { 
    return (
    <View style={styles.loginContainer}> 
     {user ? <Text>Hi, {user.name}!</Text> : <Text>NOT Logged in!</Text>} 
     <Button title="Log In" onPress={doUserLogin} /> 
    </View> 
); 
}; 

export default compose(
    connect((state, props) => ({ 
    ...state.user, 
    })), 
    withHandlers({ 
    doUserLogin: props => 
     (event) => { 
     console.log('LOGIN USER IN HANDLER'); // <-- THIS IS WORKING 
     loginUser(); 
     }, 
    }), 
)(LoginScreen); 

doUserLogin()處理程序依次調用我的行動loginUser()文件:

userActions.js:

import { LOGIN_REQUEST } from './actionTypes'; 

export const loginUser =() => { 
    return (dispatch) => { 
    console.log('In action'); // <-- THIS IS WORKING 
    dispatch({ type: LOGIN_REQUEST }); 
    }; 
}; 

到目前爲止,這麼好。但是,當我dispatch(),我的減速機從來沒有被稱爲。但減速撿其他行動(從導航等) - 它根本不是從loginUser()收到上述動作:

userReducer.js:

import { LOGIN_REQUEST } from './actionTypes'; 

const userReducer = (state = initialState, action) => { 
    console.log('In reducer'); <-- ** THIS IS NEVER CALLED ** 

    switch (action.type) { 
    case LOGIN_REQUEST: 
     return Object.assign({}, state, { 
     isFetching: true, 
     }); 
    case LOGOUT: 
     return initialState; 
    default: 
     return state; 
    } 
}; 
export default userReducer; 

任何建議將不勝讚賞。

回答

1

好吧,看起來我能弄清楚這一點。簡而言之,在loginScreen.js我需要添加mapStateToPropsmapDispatchToProps函數,它們被傳遞給connectwithHandlers然後dispatchloginUser()函數在我的動作文件中作爲道具。

更新loginScreen.js

import React from 'react'; 
import { Button, Text, View } from 'react-native'; 
import { connect } from 'react-redux'; 
import { withHandlers, compose } from 'recompose'; 
import { loginUser } from './user/userActions'; 

const LoginScreen = ({ user, doUserLogin }) => { 
    return (
    <View style={styles.loginContainer}> 
     {user ? <Text>Hi, {user.name}!</Text> : <Text>NOT Logged in!</Text>} 
     <Button title="Log In" onPress={doUserLogin} /> 
    </View> 
); 
}; 

const mapStateToProps = state => ({ 
    ...state.user, 
}); 

const mapDispatchToProps = dispatch => ({ 
    loginUser:() => { 
    dispatch(loginUser()); 
    }, 
}); 

export default compose(
    connect(mapStateToProps, mapDispatchToProps), 
    withHandlers({ 
    doUserLogin: props => 
    () => { 
     console.log('LOGIN USER IN HANDLER'); 
     props.loginUser(); 
     }, 
    }), 
)(LoginScreen); 

任何其他意見/建議仍然可以理解的。

1

實際上,對於這個特殊的情況,你可以完全拋棄與幫手。

您只需將動作創建者傳遞給react-redux connect函數,以便將其綁定到調度函數,就像您所示。更多,請查看connect文檔。您可以在連接的第三個參數中訪問組件的道具,並進一步創建依賴道具的處理程序。

你的情況可能是這樣的

const mergeProps = (stateProps, dispatchProps, ownProps) => { 
     return Object.assign({}, ownProps, stateProps, dispatchProps, { 
      doUserLogin:() => { 
      console.log('LOGIN USER IN HANDLER'); 
      console.log('accessing a prop from the component', ownProps.user); 
      dispatchProps.loginUser(); 
      } 
     }); 
     } 
     export default connect(mapStateToProps, 
           mapDispatchToProps, 
           mergeProps)(LoginScreen); 

注意我們是如何創造新的功能,這將作爲一個新的道具組件,以類似的方式來withHandler幫手

+0

嗨,何塞。感謝你的回答!不確定你到底在說什麼。你可以用一些代碼來擴展答案嗎? – GollyJer

+0

@GollyJer在代碼中添加了一個小例子... –

相關問題