我在redux中的一个动作中调用了API。
export const registerUser = registeredUserData => async dispatch => {
let messages;
try {
const response = await axios.post('/users/register', registeredUserData);
messages = response.data
} catch (error) {
if (error.response) {
messages = error.response.data
}
}
dispatch({
type: REGISTER_USER,
messages,
});
};
将表格汇总后会调用此操作。
const onRegisterUser = (e) => {
e.preventDefault();
registerUser(registeredUserData);
};
如果通话成功,我想重定向到另一个页面。
我面临的问题是在这种情况下我不知道如何实现history.push()
。
如果我将其放在registerUser(registeredUserData);
之后的组件的方法内部,那么无论调用响应如何,它都会立即被调用。而且我不确定从操作本身重定向是否是个好主意。
所有帮助将不胜感激。
答案 0 :(得分:1)
在您的示例中,您的操作registerUser
是一个承诺,因为它是一个async
函数。因此,您可以将onRegisterUser
改写成这样:
const onRegisterUser = (e) => {
e.preventDefault();
registerUser(registeredUserData)
.then(() => /* success */)
.catch(error => /* handle my failure */)
};
话虽如此,您可能需要考虑为网络呼叫创建SUCCESS
和FAILURE
操作。这样,您就可以根据注册用户api调用来更新redux的状态。
您可以将thunk修改为如下形式:
export const registerUser = registeredUserData => async dispatch => {
try {
const response = await axios.post('/users/register', registeredUserData);
dispatch({
type: REGISTER_USER_SUCCESS,
messages: response.data,
});
} catch (error) {
if (error.response) {
dispatch({
type: REGISTER_USER_FAILURE,
messages: error.response.data,
});
}
}
};
然后您可以使用React生命周期方法之一来检查redux更改中的状态。假设该代码段正在使用react-redux和connect
。
您可能还想考虑研究action creators。
使用React生命周期方法的另一种方法是使用类似redux-saga的东西,它可以发出SUCCESS
和FAILURE
动作的信号,并代表您执行history.push。
您可能还想看看react router,如果您还没有的话。它提供了访问历史记录和管理路由的方法。
在您的示例中,异步/等待的目的是不必使用嵌套的Promise链。
您的try / catch块等效于then / catch。因此,如果您想使用上面的方法并在响应为400时捕获它,您将需要删除try catch并处理onRegisterUser
中的错误(不建议),或者您需要重新抛出该错误调用catch
时会调用registerUser
。
这是registerUser
上的一个示例,当响应失败时,该示例应返回捕获。
export const registerUser = registeredUserData => async dispatch => {
try {
const response = await axios.post('/users/register', registeredUserData);
await dispatch({
type: REGISTER_USER,
messages: response.data,
});
} catch (error) {
if (error.response) {
await dispatch({
type: REGISTER_USER,
messages: error.response.data,
isError: true,
});
throw new Error(error.response.data);
}
}
};
您可能想通过装饰错误对象来将throw new Error(error.response.data)
替换为更具体的内容。
答案 1 :(得分:0)
您快到了。在您的组件中,将this.props.history
作为参数传递给redux操作。从那里,在分派操作后,您可以重定向到其他页面。
附言:从动作本身重定向是一个不错的主意。
在您的组件内部:
const onRegisterUser = (e) => {
e.preventDefault();
registerUser(registeredUserData, this.props.history);
};
内部行动:
export const registerUser = (registeredUserData, history) => async dispatch => {
let messages;
try {
const response = await axios.post('/users/register', registeredUserData);
messages = response.data
} catch (error) {
if (error.response) {
messages = error.response.data
}
}
dispatch({
type: REGISTER_USER,
messages,
});
history.push('/redirect-route);
};
答案 2 :(得分:0)
嗨艾伦,
您基本上可以从this.props.history.push
中获得Router
,并将其传递给应用程序中所有Route
子组件。
您可以通过console.log('__props__', this.props)
方法中的render
对该组件进行确认。
为了实现这一点,我建议将其作为对您的操作registerUser
的回调发送,以实现此目的:
cb
添加到您的操作中: export const registerUser = registeredUserData => async dispatch => {
let messages;
try {
const response = await axios.post('/users/register', registeredUserData);
messages = response.data
} catch (error) {
if (error.response) {
messages = error.response.data
}
}
dispatch({
type: REGISTER_USER,
messages,
});
// maybe you want a conditional redirect?
if(/*somecondition to check data or error?*/){
cb && cb(); //if callback exists, invoke it
}
};
onRegisterUser
: const onRegisterUser = (e) => {
e.preventDefault();
registerUser(registeredUserData, () => {
this.props.history.push(//route);
});
};
希望能奏效,否则请描述行为。