如何确保在导航到另一个页面之前完成减速器响应操作?
How do I make sure that reducer response action is done before navigating to another page?
我目前正在将 Redux Saga 与 React Native 结合使用,我对如何正确处理在我导航到另一个页面之前 reducer 操作未完成触发成功或失败操作的情况有疑问。在导航到另一个页面之前,我需要等到触发成功或失败操作,但它仍然可以导航。
我设置了我的代码,以便它在导航之前检查加载或错误状态,但导航仍然会发生。我认为这是因为 updateItems 是异步的,并且在响应返回之前处理代码执行得如此之快,例如如果我确实遇到错误,页面将导航离开而不是等待,以便我可以在页面上显示错误。
我认为这可能与我需要在我的减速器中添加的东西有关,但我不确定。
这是我点击的触发 reducer 调用的方法,导航一切正常。
updateItems = () => {
const { code } = this.state;
const { loading, error } = this.props;
const id = this.props.navigation.state.params.id;
this.props.updateItems({
id: id,
code: code,
});
if (!loading && !error) {
this.props.navigation.navigate("newPage");
}
};
这是减速器本身:
const UPDATE_ITEMS_REQUEST = "UPDATE_ITEMS_REQUEST";
const UPDATE_ITEMS_SUCCESS = "UPDATE_ITEMS_SUCCESS";
const UPDATE_ITEMS_FAILURE = "UPDATE_ITEMS_FAILURE";
export default (itemsReducer = (
state = {
data: {
items: {},
},
error: null,
loading: false,
},
{ type, payload },
) => {
switch (type) {
case UPDATE_ITEMS_REQUEST:
return Object.assign({}, state, { loading: true, error: null });
case UPDATE_ITEMS_FAILURE:
return Object.assign({}, state, { loading: false, error: payload });
case UPDATE_ITEMS_SUCCESS:
return {
loading: false,
error: null,
data: payload,
};
default:
return state;
}
});
export function updateItems(payload) {
return { type: UPDATE_ITEMS_REQUEST, payload };
}
export function updateItemsFailure(payload) {
return { type: UPDATE_ITEMS_FAILURE, payload };
}
export function updateItemsSuccess(payload) {
return { type: UPDATE_ITEMS_SUCCESS, payload };
}
function* updateItemsSaga(payload) {
const response = yield call(putItems, payload);
if (response.ok) {
yield put(updateItemsSuccess(payload));
} else {
yield put(
updateItemsFailure("There has been an error"),
);
}
}
export function* watchUpdateItems() {
yield takeLatest(UPDATE_ITEMS_REQUEST, updateItemsSaga);
}
// API
const putItems = async payload => {
const res = await fetch(
`${env.url}/updateItems`,
{
method: "PUT",
headers: {
Accept: "application/json",
"Content-Type": "application/json",
},
body: JSON.stringify({
id: payload.payload.id,
code: payload.payload.code,
}),
},
);
if (!res.ok)
return {
status: res.status,
ok: false,
};
const response = await res.json();
response.status = res.status;
response.ok = res.ok;
return response;
};
- 您可以使用 react routers useHistory 将用户重定向到 redux 操作中的新路由 more info on how to route
- 您可以添加一个标志并将其设置为 true 作为响应
看来问题出在updateItems
。它有一个具有两个属性 { loading, error }
的内部范围。因为这不是一个生成器函数,一旦这个函数开始执行,一个动作 updateItems
被触发(这很好),然后导航发生,因为函数检查 { loading, error }
(这是false
& null
相应地)。
解决方案可以使用 updateItemsSaga
中的导航部分,如下所示:
function* updateItemsSaga(payload) {
const response = yield call(putItems, payload);
if (response.ok) {
yield put(updateItemsSuccess(payload));
this.props.navigation.navigate("newPage");
} else {
yield put(
updateItemsFailure("There has been an error"),
);
}
}
或者,您可以从 updateItems
中提取条件并在您的组件本身中使用它:
const OldPage = ({ loading, error }) => {
if (loading) {
return <div>Loading... </div>
} else if(error) {
return <ErrorPage status="404">;
} else {
return <NewPage>;
}
};
两者都应该阻止导航发生,直到项目更新成功。希望对你有帮助
我目前正在将 Redux Saga 与 React Native 结合使用,我对如何正确处理在我导航到另一个页面之前 reducer 操作未完成触发成功或失败操作的情况有疑问。在导航到另一个页面之前,我需要等到触发成功或失败操作,但它仍然可以导航。
我设置了我的代码,以便它在导航之前检查加载或错误状态,但导航仍然会发生。我认为这是因为 updateItems 是异步的,并且在响应返回之前处理代码执行得如此之快,例如如果我确实遇到错误,页面将导航离开而不是等待,以便我可以在页面上显示错误。
我认为这可能与我需要在我的减速器中添加的东西有关,但我不确定。
这是我点击的触发 reducer 调用的方法,导航一切正常。
updateItems = () => {
const { code } = this.state;
const { loading, error } = this.props;
const id = this.props.navigation.state.params.id;
this.props.updateItems({
id: id,
code: code,
});
if (!loading && !error) {
this.props.navigation.navigate("newPage");
}
};
这是减速器本身:
const UPDATE_ITEMS_REQUEST = "UPDATE_ITEMS_REQUEST";
const UPDATE_ITEMS_SUCCESS = "UPDATE_ITEMS_SUCCESS";
const UPDATE_ITEMS_FAILURE = "UPDATE_ITEMS_FAILURE";
export default (itemsReducer = (
state = {
data: {
items: {},
},
error: null,
loading: false,
},
{ type, payload },
) => {
switch (type) {
case UPDATE_ITEMS_REQUEST:
return Object.assign({}, state, { loading: true, error: null });
case UPDATE_ITEMS_FAILURE:
return Object.assign({}, state, { loading: false, error: payload });
case UPDATE_ITEMS_SUCCESS:
return {
loading: false,
error: null,
data: payload,
};
default:
return state;
}
});
export function updateItems(payload) {
return { type: UPDATE_ITEMS_REQUEST, payload };
}
export function updateItemsFailure(payload) {
return { type: UPDATE_ITEMS_FAILURE, payload };
}
export function updateItemsSuccess(payload) {
return { type: UPDATE_ITEMS_SUCCESS, payload };
}
function* updateItemsSaga(payload) {
const response = yield call(putItems, payload);
if (response.ok) {
yield put(updateItemsSuccess(payload));
} else {
yield put(
updateItemsFailure("There has been an error"),
);
}
}
export function* watchUpdateItems() {
yield takeLatest(UPDATE_ITEMS_REQUEST, updateItemsSaga);
}
// API
const putItems = async payload => {
const res = await fetch(
`${env.url}/updateItems`,
{
method: "PUT",
headers: {
Accept: "application/json",
"Content-Type": "application/json",
},
body: JSON.stringify({
id: payload.payload.id,
code: payload.payload.code,
}),
},
);
if (!res.ok)
return {
status: res.status,
ok: false,
};
const response = await res.json();
response.status = res.status;
response.ok = res.ok;
return response;
};
- 您可以使用 react routers useHistory 将用户重定向到 redux 操作中的新路由 more info on how to route
- 您可以添加一个标志并将其设置为 true 作为响应
看来问题出在updateItems
。它有一个具有两个属性 { loading, error }
的内部范围。因为这不是一个生成器函数,一旦这个函数开始执行,一个动作 updateItems
被触发(这很好),然后导航发生,因为函数检查 { loading, error }
(这是false
& null
相应地)。
解决方案可以使用 updateItemsSaga
中的导航部分,如下所示:
function* updateItemsSaga(payload) {
const response = yield call(putItems, payload);
if (response.ok) {
yield put(updateItemsSuccess(payload));
this.props.navigation.navigate("newPage");
} else {
yield put(
updateItemsFailure("There has been an error"),
);
}
}
或者,您可以从 updateItems
中提取条件并在您的组件本身中使用它:
const OldPage = ({ loading, error }) => {
if (loading) {
return <div>Loading... </div>
} else if(error) {
return <ErrorPage status="404">;
} else {
return <NewPage>;
}
};
两者都应该阻止导航发生,直到项目更新成功。希望对你有帮助