Programing

React redux에서 가져 오기 오류를 처리하는 가장 좋은 방법은 무엇입니까?

crosscheck 2020. 9. 1. 07:02
반응형

React redux에서 가져 오기 오류를 처리하는 가장 좋은 방법은 무엇입니까?


클라이언트 용 감속기가 하나 있고 AppToolbar 용 감속기가 하나 있고 다른 감속기가 있습니다.

이제 클라이언트를 삭제하기위한 가져 오기 작업을 생성했다고 가정 해 보겠습니다. 실패하면 Clients reducer에 몇 가지 작업을 수행해야하는 코드가 있지만 AppToolbar에 일부 전역 오류를 표시하고 싶습니다.

그러나 Clients와 AppToolbar 감속기는 상태의 동일한 부분을 공유하지 않으며 감속기에서 새 작업을 만들 수 없습니다.

그렇다면 전역 오류를 어떻게 표시한다고 가정합니까? 감사

업데이트 1 :

este devstack을 사용한다는 것을 언급하는 것을 잊었습니다.

업데이트 2 : 나는 Eric의 대답을 올바른 것으로 표시했지만 este에서 사용하는 솔루션은 Eric과 Dan의 대답의 조합과 비슷하다고 말해야합니다 ... 코드에서 가장 적합한 것을 찾아야합니다 .. .


"전역 오류"라는 개념을 errors원하면 addError, removeError 등의 작업을 수신 할 수있는 감속기를 만들 수 있습니다 . 그런 다음 Redux 상태 트리에 연결하여 state.errors적절한 곳에 표시 할 수 있습니다.

이 당신이 접근 할 수있는 여러 가지 방법이 있지만, 일반적인 생각은 글로벌 오류 / 메시지가 완전히 분리 살고 자신의 감속기를받을만한 것입니다 <Clients />/ <AppToolbar />. 물론 이러한 구성 요소 중 하나에 액세스해야하는 경우 필요한 곳에 소품으로 errors전달할 errors수 있습니다.

업데이트 : 코드 예

다음은 "전역 오류" errors를 최상위 수준으로 전달 <App />하고 조건부로 렌더링하는 경우 ( 오류가있는 경우) 어떻게 보일지에 대한 한 가지 예입니다 . react-redux를connect 사용 하여 <App />구성 요소를 일부 데이터에 연결합니다.

// App.js
// Display "global errors" when they are present
function App({errors}) {
  return (
    <div>
      {errors && 
        <UserErrors errors={errors} />
      }
      <AppToolbar />
      <Clients />
    </div>
  )
}

// Hook up App to be a container (react-redux)
export default connect(
  state => ({
    errors: state.errors,
  })
)(App);

그리고 액션 생성자에 관한 한 응답에 따라 성공 실패 ( redux-thunk )를 전달 합니다.

export function fetchSomeResources() {
  return dispatch => {
    // Async action is starting...
    dispatch({type: FETCH_RESOURCES});

    someHttpClient.get('/resources')

      // Async action succeeded...
      .then(res => {
        dispatch({type: FETCH_RESOURCES_SUCCESS, data: res.body});
      })

      // Async action failed...
      .catch(err => {
        // Dispatch specific "some resources failed" if needed...
        dispatch({type: FETCH_RESOURCES_FAIL});

        // Dispatch the generic "global errors" action
        // This is what makes its way into state.errors
        dispatch({type: ADD_ERROR, error: err});
      });
  };
}

감속기는 단순히 오류 배열을 관리하여 항목을 적절하게 추가 / 제거 할 수 있습니다.

function errors(state = [], action) {
  switch (action.type) {

    case ADD_ERROR:
      return state.concat([action.error]);

    case REMOVE_ERROR:
      return state.filter((error, i) => i !== action.index);

    default:
      return state;
  }
}

Erik’s answer is correct but I would like to add that you don’t have to fire separate actions for adding errors. An alternative approach is to have a reducer that handles any action with an error field. This is a matter of personal choice and convention.

For example, from Redux real-world example that has error handling:

// Updates error message to notify about the failed fetches.
function errorMessage(state = null, action) {
  const { type, error } = action

  if (type === ActionTypes.RESET_ERROR_MESSAGE) {
    return null
  } else if (error) {
    return error
  }

  return state
}

The approach I'm currently taking for a few specific errors (user input validation) is to have my sub-reducers throw an exception, catch it in my root reducer, and attach it to the action object. Then I have a redux-saga that inspects action objects for an error and update the state tree with error data in that case.

So:

function rootReducer(state, action) {
  try {
    // sub-reducer(s)
    state = someOtherReducer(state,action);
  } catch (e) {
    action.error = e;
  }
  return state;
}

// and then in the saga, registered to take every action:
function *errorHandler(action) {
  if (action.error) {
     yield put(errorActionCreator(error));
  }
}

And then adding the error to the state tree is as Erik describes.

I use it pretty sparingly, but it keeps me from having to duplicate logic which legitimately belongs in the reducer (so it can protect itself from an invalid state).


write custom Middleware to handle all the api related error. In this case your code will be more cleaner.

   failure/ error actin type ACTION_ERROR

   export default  (state) => (next) => (action) => {

      if(ACTION_ERROR.contains('_ERROR')){

       // fire error action
        store.dispatch(serviceError());

       }
}

what I do is I centralize all error handling in the effect on a per effect basis

/**
 * central error handling
 */
@Effect({dispatch: false})
httpErrors$: Observable<any> = this.actions$
    .ofType(
        EHitCountsActions.HitCountsError
    ).map(payload => payload)
    .switchMap(error => {
        return of(confirm(`There was an error accessing the server: ${error}`));
    });

You can use axios HTTP client. It already has implemented Interceptors feature. You can intercept requests or responses before they are handled by then or catch.

https://github.com/mzabriskie/axios#interceptors

// Add a request interceptor
axios.interceptors.request.use(function (config) {
    // Do something before request is sent
    return config;
  }, function (error) {
    // Do something with request error
    return Promise.reject(error);
  });

// Add a response interceptor
axios.interceptors.response.use(function (response) {
    // Do something with response data
    return response;
  }, function (error) {
    // Do something with response error
    return Promise.reject(error);
  });

참고URL : https://stackoverflow.com/questions/34403269/what-is-the-best-way-to-deal-with-a-fetch-error-in-react-redux

반응형