传奇异步请求后如何设置状态
how to setstate after saga async request
我在我的项目中使用 redux-saga。
我以前用过 redux-thunk,所以我不能设置一些异步请求的结束。喜欢
this.props.thunkAsync()
.then(){
this.setState({ '' });
}
因为thunk return的承诺,我可以使用'then'。
但我不能用 saga 做到这一点,因为 saga 没有 return 承诺。
所以我在 componentWillReceiveProps 中通过检查标志道具(如 REQUEST_SUCCESS、REQUEST_WAITING...)已更改。
我认为这不是解决这个问题的好方法。
所以..我的问题是当异步请求在 redux-saga 中结束时我该如何做一些工作!
But i can't do this with saga, because saga doesn't return promise
Redux-saga
与 thunk
略有不同,因为它是流程管理器,而不是简单的中间件:thunk
仅对触发的操作执行反应,但 saga
有自己的"process"(正式回调刻度域)并且可以通过效果操作操作。
使用 redux-saga
执行异步操作的常用方法是将原始操作拆分为 ACTION_REQUEST
、ACTION_SUCCESS
和 ACTION_FAILURE
变体。然后 reducer 只接受 SUCCESS/FAILURE 操作,并且可能接受 optimistic updates 的 REQUEST。
在这种情况下,您的 saga
流程可以如下所示
function* actionNameSaga(action) {
try {
const info = yield call(fetch, { params: action.params }
yield put('ACTION_NAME_SUCCESS', info)
} catch(err) {
yield put('ACTION_NAME_FAILURE', err)
}
function* rootSaga() {
yield takeEvery('ACTION_NAME', actionNameSaga)
}
请记住,yield
操作本身与承诺等待无关 - 它只是将异步等待委托给 saga 进程管理器。
您发出的每个 api 调用都作为异步请求处理,但在 saga 中使用生成器函数处理。
因此,在成功调用 api 之后,您可以执行以下可能的操作。
- 再打一个api电话
function* onLogin(action) {
try {
const { userName, password } = action;
const response = yield call(LoginService.login, userName, password);
yield put(LoginService.loginSuccess(response.user.id));
const branchDetails = yield call(ProfileService.fetchBranchDetails, response.user.user_type_id);
yield put(ProfileActions.fetchBranchDetailsSuccess(branchDetails));
} catch (error) {
yield put(ProfileActions.fetchUserDetailsError(error));
}
}
成功后回调api
onLoginClick() {
const { userName, password } = this.state;
this.props.login(userName, password, this.onLoginSuccess);
}
onLoginSuccess(userDetails) {
this.setState({ userDetails });
}
function *onLogin(action) {
try {
const { userName, password, onLoginSuccess } = action;
const response = yield call(LoginService.login, userName, password);
if (onLoginSuccess) {
onLoginSuccess(response);
}
yield put(LoginService.loginSuccess(response.user.id));
const branchDetails = yield call(ProfileService.fetchBranchDetails,
response.user.user_type_id);
yield put(ProfileActions.fetchBranchDetailsSuccess(branchDetails));
} catch (error) {
yield put(ProfileActions.fetchUserDetailsError(error));
}
}
更新 Reducer State 并通过 mapStateToProps 从 props 获取
yield put(LoginService.loginSuccess(response.user.id));
@connect(
state => ({
usedDetails: state.user.get('usedDetails'),
})
)
static getDerivedStateFromProps(nextProps, prevState) {
const { usedDetails } = nextProps;
return {
usedDetails
}
}
你可以这样做。从组件 props 调用 saga 方法并传递成功或失败后要执行的函数,如下所示
export function* login({ payload }) {
const url = 'localhost://login.json';
try {
const response = yield call(App_Service, { url, method: 'GET' });
if (response.result === 'ok' && response.data.body) {
yield put(fetchDataActionCreators.getLoginSuccess(response.data.body));
//function passed as param from component, pass true if success
payload.callback(true);
}
} catch (e) {
//function passed as param from component, pass false if failure
payload.callback(false);
console.log(e);
}
}
export function* watchLogin() {
while (true) {
const action = yield take(LOGIN);
yield* login(action);
}
}
export default function* () {
yield all([
fork(watchLogin)
]);
}
In component call call setState method in the function you pass to saga as param
login() {
// store
this.props.getServiceDetails({
callback:(success) => this.onLoginSuccess(success)
})
}
onLoginSuccess = (success) => {
this.setState({
login:success
})
alert('login '+success)
}
我遇到了同样的问题...
我的解决方案是将调度包装在一个 promise 中,并在 saga 函数中调用 resolve 和 reject...
我创建了一个挂钩来包装调度。你可以在这里看到我的例子:
https://github.com/ricardocanelas/redux-saga-promise-example
希望对大家有所帮助。
我在我的项目中使用 redux-saga。 我以前用过 redux-thunk,所以我不能设置一些异步请求的结束。喜欢
this.props.thunkAsync()
.then(){
this.setState({ '' });
}
因为thunk return的承诺,我可以使用'then'。 但我不能用 saga 做到这一点,因为 saga 没有 return 承诺。 所以我在 componentWillReceiveProps 中通过检查标志道具(如 REQUEST_SUCCESS、REQUEST_WAITING...)已更改。 我认为这不是解决这个问题的好方法。
所以..我的问题是当异步请求在 redux-saga 中结束时我该如何做一些工作!
But i can't do this with saga, because saga doesn't return promise
Redux-saga
与 thunk
略有不同,因为它是流程管理器,而不是简单的中间件:thunk
仅对触发的操作执行反应,但 saga
有自己的"process"(正式回调刻度域)并且可以通过效果操作操作。
使用 redux-saga
执行异步操作的常用方法是将原始操作拆分为 ACTION_REQUEST
、ACTION_SUCCESS
和 ACTION_FAILURE
变体。然后 reducer 只接受 SUCCESS/FAILURE 操作,并且可能接受 optimistic updates 的 REQUEST。
在这种情况下,您的 saga
流程可以如下所示
function* actionNameSaga(action) {
try {
const info = yield call(fetch, { params: action.params }
yield put('ACTION_NAME_SUCCESS', info)
} catch(err) {
yield put('ACTION_NAME_FAILURE', err)
}
function* rootSaga() {
yield takeEvery('ACTION_NAME', actionNameSaga)
}
请记住,yield
操作本身与承诺等待无关 - 它只是将异步等待委托给 saga 进程管理器。
您发出的每个 api 调用都作为异步请求处理,但在 saga 中使用生成器函数处理。
因此,在成功调用 api 之后,您可以执行以下可能的操作。
- 再打一个api电话
function* onLogin(action) { try { const { userName, password } = action; const response = yield call(LoginService.login, userName, password); yield put(LoginService.loginSuccess(response.user.id)); const branchDetails = yield call(ProfileService.fetchBranchDetails, response.user.user_type_id); yield put(ProfileActions.fetchBranchDetailsSuccess(branchDetails)); } catch (error) { yield put(ProfileActions.fetchUserDetailsError(error)); } }
成功后回调api
onLoginClick() { const { userName, password } = this.state; this.props.login(userName, password, this.onLoginSuccess); } onLoginSuccess(userDetails) { this.setState({ userDetails }); } function *onLogin(action) { try { const { userName, password, onLoginSuccess } = action; const response = yield call(LoginService.login, userName, password); if (onLoginSuccess) { onLoginSuccess(response); } yield put(LoginService.loginSuccess(response.user.id)); const branchDetails = yield call(ProfileService.fetchBranchDetails, response.user.user_type_id); yield put(ProfileActions.fetchBranchDetailsSuccess(branchDetails)); } catch (error) { yield put(ProfileActions.fetchUserDetailsError(error)); }
}
更新 Reducer State 并通过 mapStateToProps 从 props 获取
yield put(LoginService.loginSuccess(response.user.id)); @connect( state => ({ usedDetails: state.user.get('usedDetails'), }) ) static getDerivedStateFromProps(nextProps, prevState) { const { usedDetails } = nextProps; return { usedDetails } }
你可以这样做。从组件 props 调用 saga 方法并传递成功或失败后要执行的函数,如下所示
export function* login({ payload }) {
const url = 'localhost://login.json';
try {
const response = yield call(App_Service, { url, method: 'GET' });
if (response.result === 'ok' && response.data.body) {
yield put(fetchDataActionCreators.getLoginSuccess(response.data.body));
//function passed as param from component, pass true if success
payload.callback(true);
}
} catch (e) {
//function passed as param from component, pass false if failure
payload.callback(false);
console.log(e);
}
}
export function* watchLogin() {
while (true) {
const action = yield take(LOGIN);
yield* login(action);
}
}
export default function* () {
yield all([
fork(watchLogin)
]);
}
In component call call setState method in the function you pass to saga as param
login() {
// store
this.props.getServiceDetails({
callback:(success) => this.onLoginSuccess(success)
})
}
onLoginSuccess = (success) => {
this.setState({
login:success
})
alert('login '+success)
}
我遇到了同样的问题...
我的解决方案是将调度包装在一个 promise 中,并在 saga 函数中调用 resolve 和 reject...
我创建了一个挂钩来包装调度。你可以在这里看到我的例子: https://github.com/ricardocanelas/redux-saga-promise-example
希望对大家有所帮助。