无法在React-Redux应用

时间:2017-04-08 01:55:11

标签: reactjs redux react-redux

我有一个登录模式。我使用动作创建器在减速器中转换isLoginModalVisible:true。在组件的onClick内调用容器内的动作创建器,如下所示:

<TextButtonRight onClick={()=> this.props.showLoginModal(true)}> 

在登录模式中,我有一个提交表单的登录按钮。我希望模态在200OK消失,否则,我在模态中显示错误消息。在登录按钮上调用此动作创建者单击:

export function logInUser(){
    console.log("Actions--> logInUser");
    //Imagine I got a 200OK
    dispatch(showLoginModal(false));

    return({
        type: UPDATE_USER_LOGGED_IN,
        payload: true
    });
}

我正在调用动作创建者从logInUser动作创建者隐藏模态,但它无法正常工作。 showLoginModal动作创建者确实被击中但它没有派遣到减速器。

这是showLoginModal动作创建者:

export function showLoginModal(bool){
    console.log("Actions--> showLoginModal:"+bool);
    return({
        type: UPDATE_LOGIN_MODAL_VISIBLE,
        payload: bool
    });
}

(如果我犯了一个菜鸟错误,我很抱歉)

编辑:

我的reducer的一部分。它确实有效,因为这就是我显示登录模式的方式。当我想隐藏它时,我传递假。有效载荷也没有问题。当我通过另一个动作创建者调用它时,console.log没有获取。当我将它传递给onClick时按下提交按钮这样工作正常: onClick={()=> this.props.showLoginModal(false)}

case UPDATE_LOGIN_MODAL_VISIBLE:
            console.log("REDUCER-->"+UPDATE_LOGIN_MODAL_VISIBLE);
            return {...state, loginModalVisible: action.payload};
            break;

CombineReducers:

const rootReducer = combineReducers({
    posts: postsReducer, 
    displayComps: displayComponentsReducer,
    form: formReducer,
    searchForm: searchFormReducer
});

编辑2:

对不起,我应该提到我正在使用thunk。我想知道是否有办法从这一个调用一个动作,如下:

req.then((response)=>{
    console.log("REQ_COMPLETE");
    dispatch({type: UPDATE_USER_LOGGED_IN, payload: true});
    //like so:
    showLoginModal(false);
    localStorage.setItem('userLoggedIn', true);
 })

而不是添加:

dispatch({type: UPDATE_LOGIN_MODAL_VISIBLE, payload: false});

从另一个动作创建者那里发送动作似乎有点笨拙。

3 个答案:

答案 0 :(得分:5)

澄清一些术语可能会有所帮助。如果这是你已经知道的东西,请提前道歉。

如果要使用redux-thunk调度多个操作,可以调度操作。这是一种常见的模式。您的logInUser()函数看起来像是一个操作。有关规范示例,请参阅fetchPostsIfNeeded() in Dan Abramov's documentation here

动作创建者只返回一个对象而不执行任何操作。填充操作(通常是异步),然后调度操作,通常通过调用操作创建者来构建操作。从操作中调度动作没有任何问题。

但是,不建议从动作创建者调用任何函数。动作创建者应返回一个简单的对象,并且没有副作用,例如showLoginModal()函数。请注意,在调用动作创建者和手动创建对象之间存在 NO BEHAVIORAL DIFFERENCE 。所以这样做:

var action = { type: UPDATE_LOGIN_MODAL_VISIBLE, payload: false }

相同

var action = showLoginModal(false)

需要注意的是:这些代码都没有做任何事情!他们创建一个对象,但不要用于任何事情。在dispatch(action)之前,您的应用中不会发生任何事情。

动作创建者和操作都必须dispatch()编辑。

  • 必须调度该操作,因为它的内部函数如何传递dispatch函数变量,而该函数又用于调度操作。
  • 必须发送行动,因为它们没有自己的功能;它们只是简单的物体。只有当它们被分派到Redux商店时才会影响商店状态。

看起来你的这个代码正在调用一个动作创建者,但没有调度它:

showLoginModal(false);

将其更改为

dispatch(showLoginModal(false));

可能会解决您的问题。

以一种帮助任何人阅读代码(包括你)来查看/记住他们只是创建一个动作的方式命名动作创建者会很有帮助。例如,您可以将showLoginModal重命名为showLoginModalAction甚至createShowLoginModalAction

logInUser()函数是一个操作(因为它调度一个动作),由于没有明确的原因,它也返回一个动作。它返回的动作永远不会被分派到商店,至少在发布的代码中,所以它没有任何效果。可能你的意图是将这个动作发送到商店,为什么不直接在那里发货呢?

logInUser(){
  dispatch( sendingLoginRequestAction() );
  someAsyncLoginFuncThatReturnsAPromise(userName, password)
  .then(result=>{
    dispatch( loginSucceededAction(result) );
    dispatch( hideLoginModalAction() );
  });
}

这些动作创建者看起来像:

sendingLoginRequestAction() { return { type: UPDATE_SENDING_LOGIN_REQUEST }; } // You don't have anything like this, but it could be used to show a Waiting animation

loginSucceededAction() { return { type: UPDATE_USER_LOGGED_IN, payload: true }; }

hideDialogModalAction { return { type: UPDATE_LOGIN_MODAL_VISIBLE, payload: false }; }

这有帮助吗?

答案 1 :(得分:4)

我认为您的部分问题是您没有使用Redux Middleware。 这是redux创建者自己的一个很好的教程:Building React Applications with Idiomatic Redux

出于您的目的,如果您合并Redux Thunk,您应该能够从一个动作创建者发送多个动作。

以下是如何做到的:

安装: npm install --save redux-thunk

将其放入您的store.js文件

import { createStore, applyMiddleware } from 'redux';
import thunk from 'redux-thunk';
import rootReducer from './reducers/index';

// Note: this API requires redux@>=3.1.0
const store = createStore(
  rootReducer,
  applyMiddleware(thunk)
);

现在,您的操作创建者将dispatchgetState可用。

export const showLoginModal = (bool) => {
    console.log("Actions--> showLoginModal:"+bool);
    return({
        type: UPDATE_LOGIN_MODAL_VISIBLE,
        payload: bool
    });
}

export const loginUser = () => (dispatch, getState) => {
  console.log("Actions--> logInUser");
  // you have complete state available as getState(), but this is
  // not a good design pattern, so use with caution
  //Imagine I got a 200OK
  dispatch(showLoginModal(false));
  dispatch({
        type: UPDATE_USER_LOGGED_IN,
        payload: true
    });
}

我希望它有所帮助。玩得开心。

答案 2 :(得分:3)

你看过redux thunk了吗?它允许您将函数传递给reducers,它允许异步调用。

然后在你的一个动作创作者中你可以写出类似的东西:

export const logUserIn () => {
    return dispatch => {
        fetch(/* hit login url*/)
             .then(res => {/* switch on res here, if login worked
                              dispatch to hide modal, else show 
                              error*/})

    }
}
希望有所帮助。