search

Home  >  Q&A  >  body text

How to log errors from within reducers

I'm new to Redux and a little confused on how to log error messages to the console. I'm using React, Redux Toolkit and TypeScript.

This is an example of a reducer I wrote:

// Reducer
const removeResourceReducer = (state: ResourceCounts, action: ResourceAction) => {
  const { id, amount } = action.payload;
  assertIsPositive(amount);
  const has = state[id] ?? 0;
  if (amount > has) {
    throw new Error(`Trying to take ${amount} ${id} from global resources only containing ${has}`);
  }
  state[id] = has - amount;
  if (state[id] === 0) {
    delete state[id];
  }
  return state;
}

// Assertion functions
export const assert = (condition: any, msg: string): asserts condition => {
  if (!condition) {
    throw new Error(`Assertion Error: ${msg}`);
  }
}

export const assertIsPositive = (num: number) => {
  return assert(num > 0, `Expected a positive number, but got ${num}`);
}

As you can see, if the amount I pass in is less than 1 or greater than the amount of available resources, an error will be thrown. I would like this error to be logged to the console so I can check it in the dev tools, but when I pass in an invalid number nothing is logged. To achieve this, I tried adding a custom middleware, wrapping next(action) in a try/catch block, the catch block calls console.error(err), I've also tried wrapping my root component renderer in a try/catch to achieve the same result - logging any unhandled errors in the application.

Googling didn't help me, so can anyone give me some ideas? I guess something in Redux or the Redux Toolkit catches the error, but I don't know what it does with the information.

P粉893457026P粉893457026309 days ago553

reply all(1)I'll reply

  • P粉872101673

    P粉8721016732024-04-06 11:19:17

    The React Redux documentation provides some middleware examples, one of which is "crash reporter".

    A simple implementation can be as follows:

    const errorLogger = store => next => action => {
      try {
        return next(action);
      } catch(error) {
        // log the error/send to analytics/crashlytics/etc
        throw error;
      }
    };
    
    configureStore({
      reducer: rootReducer,
      middleware: getDefaultMiddleware =>
        getDefaultMiddleware().concat(
          errorLogger,
        ),
      preloadedState,
    });
    

    Demo

    reply
    0
  • Cancelreply