Real-world mechanisms, state management, edge cases, performance trade-offs, and practical coding.
dispatch and the reducer — it can log, transform, delay, or swallow actions.store => next => action => result. Calling next(action) forwards to the next middleware; calling dispatch(...) instead restarts from the chain's head.configureStore({ middleware: g => g().concat(logger) }).const fetchUser = id => async (dispatch, getState) => {
dispatch(loadingStarted());
try { dispatch(loadSucceeded(await api.getUser(id))); }
catch (e) { dispatch(loadFailed(e.message)); }
};
(dispatch, getState) — enabling side effects and multi-step dispatches.const fetchUser = createAsyncThunk('user/fetch', async (id, { signal }) =>
api.getUser(id, { signal }));
Emits three actions automatically: pending, fulfilled (payload = return value), rejected (payload = serialized error unless rejectWithValue).
extraReducers builders — keeps slice reducers declarative.thunk.dispatch(fetchUser.abort()) or condition option), single-flight dedupe per arg (condition callback), and typed payload preparation via payloadCreator's second arg { dispatch, getState, rejectWithValue }.getState() shows newer id.const selectVisible = createSelector(
[selectTodos, selectFilter],
(todos, filter) => todos.filter(t => matches(t, filter)) // reruns only on input change
);
useSelector runs after EVERY action; unmemoized derived selectors recompute (and produce new array references → re-renders) even when inputs didn't change.You've completed the 5 free sample questions. Get unrestricted lifetime access to every question, model answer, implementation challenge, and all 27+ technologies for a single payment.
₹399 India / $9 International · One-time settlement · Zero subscription