DEV Community

Discussion on: Mocking redux useSelector-hook

Collapse
murilovarela profile image
Murilo Varela

In the RTL documentation, you can find an explanation of how you can wrap your component with the store provider. (testing-library.com/docs/example-r...)

I like to test whether my actions are called or not, and also pass a custom initialState. The aproach I use is the following above:

export function renderWithRedux(ui, { initialState = initialStateOriginal } = {}) {
  const actions = [];
  const observerMiddleware = () => next => action => {
    actions.push(action);
    return next(action);
  };
  const store = createStore(reducer, initialState, applyMiddleware(observerMiddleware));
  const utils = {
    dispatch(action) {
      return store.dispatch(action);
    },
    getDispatchedActions() {
      return actions;
    },
    getState() {
      return store.getState();
    },
  };
  return {
    ...render(<Provider store={store}>{ui}</Provider>),
    ...utils,
  };
}
Enter fullscreen mode Exit fullscreen mode

So you can get the dispatch, getDispatchedActions, and getState from the render result.

const { getByText, getDispatchedActions, getAllByTestId, dispatch } = renderWithRedux(
      <MyComponent />,
      { initialState: {......} }
    );
Enter fullscreen mode Exit fullscreen mode
Collapse
gugol2 profile image
Watchmaker

When I do this, my calls to the components inside MyComponent get called just twice as many times as before using useSelector...

Somehow useSelector is provoking more re-renders.

Collapse
gugol2 profile image
Watchmaker • Edited

I found why...
Selectors have to return only one single field of the state that can be ONLY calculated used itself and no other slices of the state.
Otherwise you have to use Reselect or another library to create memoized selectors that compute and/or return multiple fields of the state.

My experience is that if your operations on the state are a bit complex maybe useSelector adds a bit too much complexity for what if offers and in that case it is maybe better stay with the connect HOC and its mapStateToProp function to operate on the state.
But if your operations on the state are simple useSelector may clear up your component a bit.

Collapse
fredrikbergqvist profile image
Fredrik Bergqvist Author

Very nice, thanks for the suggestion!