使用放入回调

Using put in callback

我正在将 react-native 与 saga 一起使用,我想在请求成功时发出警报。我想知道如何在警报回调中放置一个动作,以及是否有更好的方法来做到这一点。

function* userRequest(action) {
    try {
        const user = yield call(Api.post, Routes.REQUEST_USER, params);
        yield put({type: types.REQUEST_OK, user: user});
    } catch(e) {
        yield put({type: types.REQUEST_FAILED, user: user});
    }
}

function* requestOk(action) {
    Alert.alert(
        'User',
        'User request ok!',
        [
            //I know this is wrong
            {text: 'OK', onPress: () => yield put({type: types.NAVIGATION_BACK})},
        ],
        { cancelable: false }
    )
}

function* userSaga() {
    yield takeEvery(types.USER_REQUEST, userRequest);
    yield takeEvery(types.REQUEST_OK, requestOk);
}

谢谢!

takeEvery 采用可选参数,所以我发现最好的方法是将您的商店传递给 saga,然后使用 store.dispatch 触发您的操作:

import {createStore} from 'redux';
const store = createStore(...)  // you'll already have this somewhere

---

function* userSaga(store) {
  yield takeEvery(types.REQUEST_OK, requestOk, store);

---

function* requestOk(store, action) {  // store is now the first arg
  Alert.alert(
    'User',
    'User request ok!',
    [
        {text: 'OK', onPress: () => store.dispatch({type: types.NAVIGATION_BACK})},
    ],
    { cancelable: false }
  )
}

您可以在承诺中编写 Alert.alert() 方法,并根据用户的选择解决或拒绝 select。

在 Promise 中创建警报

function showAlert(){
  return new Promise((resolve, reject) => {
    Alert.alert(
      'User',
      'User request ok!',
      [
        {text: 'OK', onPress: () => resolve('confirmed') },
        {text: 'Cancel', onPress: () => reject('canceled')}
      ],
      { cancelable: false }
    )
  })
}

在你的发电机中...

function* requestOK(){
   try{
     const confirm = yield call(showAlert);

     //promise resolved, user confirmed
     yield put({type: types.NAVIGATION_BACK});

   }catch(error){
      //user selected cancel
   }
}

https://github.com/redux-saga/redux-saga/issues/508#issuecomment-243336353

您可以使用 eventChannel

function alert(){
  return eventChannel(emitter => {
    Alert.alert(
      'User',
      'User request ok!',
      [
        {text: 'OK', onPress: () => emitter('OK')},
      ],
      { cancelable: false }
    )
  })
}

function* saga(){
  yield takeEvery(types.REQUEST_OK, function*(){
    const channel = yield alert()
    // while(true){
    const button = yield take(channel)
    yield put({type: types.NAVIGATION_BACK})
    // }
  });
}