2017-08-03 27 views
0

为我的项目我正在使用Redux-Form异步验证使用还原thunk

如果密码正确,我想验证密码并自动将用户登录到系统。用户登录后,我更新了一些内部的重复状态。要做到这一点,我使用了与操作方法的redux thunk。

我面临的问题是,redux thunk操作无法返回async redux-form验证所需的Promise。

这是错误,我有:

asyncValidate function passed to reduxForm must return a promise 

是否有人知道问题出在哪里?

这里是我使用的代码:

asyncValidate.js

import {logIn} from '../user/actions'; 

const asyncValidate = (values, dispatch) => { 
    return logIn(values.booker.email, values.booker.password); 


} 

export default asyncValidate 

用户登录操作

export const logIn = (email, password) => (dispatch) => 
new Promise(function (resolve, reject) { 
    axios.post('/login_check', qs.stringify({ 
     _username: email, 
     _password: password, 
     _csrf_token: CSRF_TOKEN 
    }), ajaxConfig) 
     .then(response => { 
      if (response.data.success !== true) { 

       dispatch({ 
        type: LOG_IN_ERROR, 
        payload: response.data.message 
       }); 
       reject(response.data.message); 

      } 
      else { 
       dispatch({ 
        type: LOG_IN_SUCCESS, 
        payload: response.data.user 
       }); 
       resolve(); 
      } 

     }) 
     .catch((error) => { 
      dispatch({ 
       type: LOG_IN_ERROR, 
       payload: error 
      }); 
      reject(error); 
     }) 

}); 

编辑1:

试图代码@Ravindra Ranwala建议,我仍然得到了同样的错误:

@Emrys Myrooin建议从行动asyncValidation功能,但终极版表格移动代码不会触发任何错误,当用户(我在这种情况下)输入错误的密码。

这里是新asyncValidate功能代码:

import {LOG_IN_ERROR, LOG_IN_SUCCESS, CSRF_TOKEN} from '../booker/actions'; 
    import axios from 'axios'; 
    const qs = require('qs'); 
    const ajaxConfig = { 
     headers: {"X-Requested-With": "XMLHttpRequest"} 
    }; 

const asyncValidate = (values, dispatch) => { 
    console.log(values); 
    return new Promise(function (resolve, reject) { 
     axios.post('/login_check', qs.stringify({ 
     _username: values.booker.email, 
     _password: values.booker.password, 
     _csrf_token: CSRF_TOKEN 
    }), ajaxConfig) 
     .then(response => { 
      console.log(response); 
      if (response.data.success !== true) { 

       dispatch({ 
        type: LOG_IN_ERROR, 
        payload: response.data.message 
       }); 
       reject(response.data.message); 

      } 
      else { 
       dispatch({ 
        type: LOG_IN_SUCCESS, 
        payload: response.data.user 
       }); 
       resolve(); 
      } 

     }) 
     .catch((error) => { 
      dispatch({ 
       type: LOG_IN_ERROR, 
       payload: error 
      }); 
      reject(error); 
     }) 
    }) 


    } 

    export default asyncValidate 

编辑2.评论

有了这个代码,更新代码,只要密码字段触发blur事件,我得到这个错误:

Uncaught Error: asyncValidate function passed to reduxForm must return a promise 

ajax请求完成后,我得到了验证错误消息,我想从开始但通过字字段未通过验证...

这是Ajax请求的错误后完成:

asyncValidate.js?9b4c:19 Uncaught (in promise) Error: Bad credentials. 

asyncValidate功能:

import {logInError, logInSuccess, CSRF_TOKEN} from '../booker/actions'; 

import axios from 'axios' 
const qs = require('qs') 
const ajaxConfig = { 
    headers: { 'X-Requested-With': 'XMLHttpRequest' }, 
} 

const asyncValidate = (values, dispatch) => { 
    axios 
     .post(
      '/login_check', qs.stringify({ 
       _username: values.booker.email, 
       _password: values.booker.password, 
       _csrf_token: CSRF_TOKEN, 
      }), ajaxConfig) 
     .then(response => { 
      console.log(response); 
      if (response.data.success) 
       dispatch(logInSuccess(response.data.user)) 
      else 
       throw new Error(response.data.message) 
     }) 
     .catch(error => { 
      dispatch(logInError(error.message)) 
      throw error 
     }) 
} 

export default asyncValidate 

减速动作:

export const logInSuccess = response => ({ 
    type: LOG_IN_SUCCESS, 
    payload: response 

}); 

export const logInError = (response) => ({ 
    type: LOG_IN_ERROR, 
    payload: response 


}); 

回答

0

你的功能logIn是一个动作创建者,它返回一个动作,这里是一个thunk。所以不,logIn的回报不是承诺。

我认为您应该将异步代码移至asyncValidate函数,并使用参数中给出的dispatch来分配要修改redux状态的操作。

编辑

您的代码应该是这样的:

import { logInError, logInSuccess, CSRF_TOKEN } from '../booker/actions' 
import axios from 'axios' 
const qs = require('qs') 
const ajaxConfig = { 
    headers: { 'X-Requested-With': 'XMLHttpRequest' }, 
} 

const asyncValidate = (values, dispatch) => 
    axios 
    .post(
     '/login_check', qs.stringify({ 
     _username: values.booker.email, 
     _password: values.booker.password, 
     _csrf_token: CSRF_TOKEN, 
     }), ajaxConfig) 
    .then(response => { 
     if (response.data.success) 
     dispatch(logInSuccess(response.data.user)) 
     else 
     throw new Error(response.data.message) 
    }) 
    .catch(error => { 
     dispatch(logInError(error.message)) 
     throw { password: error.message }) 
    }) 

而在你的文件../booker/actions你应该有

export const logInSuccess = user => ({ 
    type: LOG_IN_ERROR, 
    payload: user 
}) 

export const logInError = (message) => ({ 
    type: LOG_IN_ERROR, 
    payload: message 
}) 

几点说明:

正如指出的oth呃回答,你不必把你的ajax调用封装成Promise,因为axios已经返回一个承诺。要拒绝then函数中的承诺,您可以合理地抛出错误。

另一个问题是,在你定义你的动作的特定文件action之外建立一个动作。否则,你将有吨重复的行动,这对维护是很糟糕的。

最后一点,您可能永远不必在条件中明确检查aBoolean === true。只要做if(aBoolean)if(!aBoolean)。如果你真的想检查你的变量实际上是一个布尔值(也是非常不寻常的),那么可以使用===

+0

我将logIn函数移到了asyncValidate函数,但由于某种原因验证没有触发。 Ajax调用执行但没有验证错误(我输入了错误的密码) – jureispro

+0

使用您的代码更新:-) –

+0

根据您的要求更新了代码。 – jureispro

0

您不必显式返回承诺。当您向商店发送操作时,thunk变得有用。尝试像这样改变你的代码。

export function login(email, password) { 
    return function(dispatch) { 
     axios.post('/login_check', qs.stringify({ 
     _username: email, 
     _password: password, 
     _csrf_token: CSRF_TOKEN 
    }), ajaxConfig) 
     .then(response => { 
      if (response.data.success !== true) { 

       dispatch({ 
        type: LOG_IN_ERROR, 
        payload: response.data.message 
       }); 

      } 
      else { 
       dispatch({ 
        type: LOG_IN_SUCCESS, 
        payload: response.data.user 
       }); 
      } 

     }) 
     .catch((error) => { 
      dispatch({ 
       type: LOG_IN_ERROR, 
       payload: error 
      }); 
     }) 
    } 
} 
+0

嗨。我试过你的代码,同样的错误仍然存​​在。问题是异步函数不会“等待”axios调用完成 – jureispro

+0

什么是您的异步​​函数? –

+0

你可以在我的文章中的原始asyncValidate.js中看到它。我将logIn函数导入asyncValidate函数,并从那里调用函数。 – jureispro