Где хорошо называть действия неудачниками и успехами в реаги-редуксе? - PullRequest
1 голос
/ 09 ноября 2019

У меня вопрос по поводу redux.

Теперь я создаю свое мобильное приложение, следуя продвинутому обучающему руководству .

В учебнике говорится, что у вас естьчтобы создать 3 действия для каждой 1 функции, поэтому я создал 3 действия для функции входа, как показано ниже:

requestSignIn
requestSignInSuccess
requestSignInFailure

Однако я не понимаю, откуда приложение должно вызывать их.

Теперь в моем приложении приложение вызывает requestSignInSuccess и requestSignInFailure в requestSignIn.

Это мой код действия:

export const REQUEST_SIGN_IN = 'REQUEST_SIGN_IN';
export const REQUEST_SIGN_IN_FAILURE = 'REQUEST_SIGN_IN_FAILURE';
export const REQUEST_SIGN_IN_SUCCESS = 'REQUEST_SIGN_IN_SUCCESS';

import firebase from 'react-native-firebase';

export function requestSignIn() {
  // start sign in function
  firebase.auth().signInWithEmailAndPassword(EMAIL, PASSWORD)
    .then(response => {
      // success, so call requestSignInSuccess() to change state
      requestSignInSuccess(response.user);
    })
    .catch(error => {
      // fail, so call requestSignInFailure() to change state
      requestSignInFailure(error);
    })

}

function requestSignInSuccess(user) {
  // save user info into state in reducer
  return {
    type: 'REQUEST_SIGN_IN_SUCCESS'
    payload: user
  }
}

function requestSignInFailure(error) {
  // save error message into state in reducer
  return {
    type: 'REQUEST_SIGN_IN_FAILURE'
    payload: error
  }
}

[Вопросы]

  • Правильно ли я придерживаюсь учебника redux? (Приложение вызывает requestSignInFailure и requestSignInSuccess в функции requestSignIn, это хорошо?)
  • Если я хочу, чтобы приложение установило флаг isLoading в состояние, какое действие должно изменить флаг?

Ответы [ 4 ]

1 голос
/ 10 ноября 2019

Попробуйте использовать промежуточное программное обеспечение redux-thunk для обработки обещаний в действиях. Вы получите выполненные, ожидающие (ваша загрузка) и неудачные действия для каждого обещания.

0 голосов
/ 09 ноября 2019

Позвольте мне попытаться ответить один на один на ваши вопросы.

Правильно ли я придерживаюсь учебника redux?

Да, вы на правильном путиВсего несколько шагов. Приведенное ниже объяснение относится к компонентам на основе классов.

Технически, если вы создали действия - как и выше в своем вопросе - тогда вам нужно отправить их в компонент для использования.

  1. Сначала необходимо отправить действия в mapDispatchToProps.
  2. Затем необходимо подключить компонент - для вызова действия requestSignIn - с хранилищем Redux.
  3. Передатьсоздал mapDispatchToProps для подключения в качестве второго параметра.

Ниже приведен следующий пример:

import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';

// ... other imports

class YourComponent extends React.Component {
     constructor (props) {
         super(props);
     }

     // ... component code
     // ... obviously this is just an example component for representation

     render() {
         return (
             <>
                 <a onClick={props.requestSignIn()}>Request Sign In</a>
             </>
         )
     }
}

const mapDispatchToProps = dispatch => {
    return bindActionCreators({ requestSignIn }, dispatch);
};


export default connect(null, mapDispatchToProps)(YourComponent);

Если я хочу, чтобы приложение имело флаг isLoadingв состояние, какое действие должно изменить флаг?

Я бы создал в редукторе новое свойство с именем isLoading, как показано ниже:

const initialState = {
    isLoading: false,
};

export default (state=initialState, action) => {
    switch(action.type) {
         case 'ENABLE_LOADING':
              return {
                   ...state,
                   isLoading: true,
              };

         case 'REQUEST_SIGN_IN_SUCCESS':
              return {
                   ...state,
                   isLoading: false,
              };

         case 'REQUEST_SIGN_IN_FAILURE':
              return {
                   ...state,
                   isLoading: false,
              };

         // ... other actions
    }
}

В вашем requestSignInдействие должно вызвать ENABLE_LOADING, как только вы начнете извлекать данные за одну строку до firebase.auth().signInWithEmailAndPassword(EMAIL, PASSWORD), тогда, надеюсь, это сработает для вас. Как и в случае с REQUEST_SIGN_IN_SUCCESS и REQUEST_SIGN_IN_FAILURE.

Чтобы получить доступ к свойствам редуктора, вам нужно использовать mapStateToProps далее.

В случае функциональных компонентов вам нужно использовать useDispatch для вызова созданных действий:

Этот хук возвращает ссылку на функцию отправки из хранилища Redux. Вы можете использовать его для отправки необходимых действий.

А для доступа к данным из хранилища есть хук, называемый useSelector:

Позволяет извлекать данныеиз состояния хранилища Redux, используя функцию селектора.

Краткий обзор:

Если вы ищете полностью рабочий пример с useSelector и useDispatch в функциональном компоненте, затем взгляните на этот репозиторий git:

https://github.com/norbitrial/react-redux-loading-data-example

В репозитории вы найдете хорошее представление о ложном вызове API, который загружает данные в таблицус индикатором загрузчика, точно так же, как вам нужно из вашего вопроса.

В случае дополнительной заинтересованности в более подробной информации, пожалуйста, найдите ссылки, которые довольно полезны:

  1. Connect: диспетчеризация действий с mapDispatchToProps
  2. Connect: извлечение данных с mapStateToProps
  3. диспетчеризация действий с useDispatch() для функционального компонента
  4. Extrобработайте данные с помощью useSelector() для функционального компонента

Надеюсь, это поможет, дайте мне знать, если вам нужны дополнительные разъяснения.

0 голосов
/ 09 ноября 2019

Я внес некоторые изменения в приведенный выше код. requestSignInFailure и requestSignInSuccess в requestSignIn хорошо вы можете использовать его, или у вас есть выбор изменить запрос thunk на запрос RSAA, но подключение его к firebase может быть затруднено.

import firebase from 'react-native-firebase';

export function requestSignIn() {
  // start sign in function
  startedRequestForSignIn()
  firebase.auth().signInWithEmailAndPassword(EMAIL, PASSWORD)
    .then(response => {
      // success, so call requestSignInSuccess() to change state
      requestSignInSuccess(response.user);
    })
    .then(()=>{
        endedRequestForSignIn()
    })
    .catch(error => {
      // fail, so call requestSignInFailure() to change state
      requestSignInFailure(error);
    })

}

function requestSignInSuccess(user) {
  // save user info into state in reducer
  return {
    type: 'REQUEST_SIGN_IN_SUCCESS'
    payload: user
  }
}

function requestSignInFailure(error) {
  // save error message into state in reducer
  return {
    type: 'REQUEST_SIGN_IN_FAILURE'
    payload: error
  }
}

function startedRequestForSignIn{
  return {
    type: 'IS_LOADING'
    payload: true
  }
}
function endedRequestForSignIn{
  return {
    type: 'IS_LOADING'
    payload: false
  }
0 голосов
/ 09 ноября 2019

Вы делаете все правильно, но чтобы сохранить код чистым и читабельным, я бы посоветовал вам извлечь все переменные типа из компонента, создать папку действий внутри src -> создать файл types.js (или любое другое имя) и переместитьвсе переменные к нему. вы можете сделать то же самое с requestSignInFailure и requestSignInSuccess (сохраняйте вещи, связанные с действием, в своей папке действий. (ЕСЛИ вы не используете ловушки реакции, потому что вы должны использовать useDispatch в функции компонента React, а не в чистой функции)). и для отправки данных в хранилище вы должны использовать dispatch (я предполагаю, что вы используете метод connect при экспорте компонента), и если вы передадите свое действие для подключения в качестве второго аргумента, функция получит вторую функцию внутри с аргументом dispatch, например

function requestSignInFailure(error) {
  // save error message into state in reducer
  function(dispatch){
      dispatch({
        type: 'REQUEST_SIGN_IN_FAILURE'
        payload: error
      })
  }
}

это то же самое, если вы передадите функцию непосредственно в connect, например, так:

connect(mapStateToProps, {
   (dispatch) => {
      dispatch({
        type: 'REQUEST_SIGN_IN_FAILURE'
        payload: error
      })
   },
   (dispatch) => {
      dispatch({
        type: 'REQUEST_SIGN_IN_SUCCESS'
        payload: success
      })
   }
})(Component);

и для изменения значения isLoading вы можете использовать componentDidMount, а действие отправки внутри componentDidMount внутри него:изменение isLoading, оно будет отправлять действие, пока компонент рендерится (монтируется) следующим образом:

function changeLoading(){
    function(dispatch){
        dispatch({
           isLoading: false
        })
    }
}

componentDidMount(){
    this.props.changeLoading();
}

export default connect(null, changeLoading)(Component)

реагирует на документы о методах жизненного цикла .

...