React-Native / Redux-Saga: как ждать окончания отправки - PullRequest
0 голосов
/ 20 февраля 2019

Сообщество Hi Stack Overflow!

Я ищу полезную практику и реализацию для ожидания отправленного действия в компоненте.

Я знаю React-Native и Redux-Saga простоскажем: не ждите этого, пусть магазин обновится, и с помощью селекторов ваш вид будет перерисован.

Все хорошо, но как справиться с такими вещами:

onPress = (object) => {
    this.props.editObject(object).then(() => { //editObject is an action
        NavigationService.navigateTo(otherScreen); 
    }).catch((error) => {
        // Handle and show validation errors
    }) 
}

Конечно, в приведенном выше примере это дает сбой, поскольку тогда нет или зацепка, так как этодействие, а не обещание ... Итак, как реализовать такой поток?

Единственное решение, которое я могу придумать, - это передать строку navigateTo в действие и перейти в самой саге, которая не является чистой.вообще ...

Любой совет?

РЕДАКТИРОВАТЬ :

Я до сих пор не нашел хорошего решения этой проблемы, и я получаювсе больше и больше разочаровываются в промежуточном программном обеспечении redux-saga.

Давайте приведем более конкретный пример: у меня есть профиль и изображение, которые необходимо обновлять (последовательно), в любой обычной js-среде это будет

try { 
    setLoading(true);
    await updateProfile(...);
    await updateProfileImage(...);
    navigate(...)
} catch (e) {
    //...
} finally {
    setLoading(false);
}

Чтобы реализовать это с помощью redux-saga, мне понадобится новый магазин (с profileUpdateDone, profileUpdateFailedStatus, profileImageUpdateDone и profileImageUpdateFailedStatus), новый редуктор, новые селекторы, ...

  • ДоДействие
  • Обновление хранилища
  • Прослушивание в componentDidUpdate для profileUpdateDone или -FailedStatus
  • Обработка ошибки или выполнение второго действия
  • Обновление хранилища
  • Прослушивание в componentDidUpdate для updateProfileImageDone или -FailedStatus
  • Обработка ошибки или навигация

Магазин становится очень грязным для добавления всего этого дерьма.Я мог бы представить одно хранилище, редуктор, действия и селекторы для каждого компонента, но я получил 58 компонентов и уже 7 хранилищ для управления глобальным состоянием приложения.Кажется нереальным иметь 65 хранилищ, 65 редукторов, 65 файлов селектора и т. Д.

Я ломал голову над поиском какого-то чистого шаблона проектирования, чтобы исправить это.Кажется, что это самая базовая из основных задач, которую любая JS-инфраструктура должна уметь легко выполнять, но по какой-то причине не в redux-saga.

Я единственный, кто сталкивается с этой проблемой, или это избыточно?сага предназначена только для небольших приложений, например, не более 20 экранов?

Ответы [ 2 ]

0 голосов
/ 22 февраля 2019

navigateTo - это больше компонент, в то время как editObject - это состояние / сага.Сага не должна знать переходы экрана.

Итак, давайте введем переменную «склеивания», которая будет обновляться сагой после завершения редактирования и которую компонент может слушать.

// Saga
function* editObject(payload) {
  try {
    // do editing
    yield put(editDone(...)); // done editing
  } catch() {...}
}

// Reducer
let initialState {
  editDone: false, // glue variable
};

objList = (state=initialState, action) => {
  switch(...) {
    case 'EDIT_DONE':
      return {...state, editDone: true }; // update glue variable
  }
}

// Component
componentDidUpdate(prevProps) {
  if (this.props.editDone && !prevProps.editDone) {
    // navigate to other screen
  }
}
0 голосов
/ 20 февраля 2019

Вы можете сохранить одно начальное состояние в вашем редукторе, скажем, isEditObjectDone:false.

Когда редуктор получает данные от действия, измените это на true.

И, На вашем экране на componentDidUpdate или componentWillReceiveProps

сделайте это,

if(this.props.isEditObjectDone){
   NavigationService.navigateTo(otherScreen); 
}

не забудьте сопоставить состояние с реквизитом.

РЕДАКТИРОВАТЬ:

сделать ваше действие, чтобы вернуть promise,

, как это,

editObject = object => dispatch =>
  new Promise((resolve, reject) => {
    //your code and dispatch thing
    // don't return dispatch instead do this
    dispatch({
    type: 'something',
    ...
     });
    if (something) 
      resolve(someData);
    else 
      reject(someError);
  });
...