Redux slices and actions help organize app data and changes in one place. They make managing app state easier and clearer.
Redux slices and actions in React Native
import { createSlice } from '@reduxjs/toolkit'; const sliceName = createSlice({ name: 'sliceName', initialState: { key: 'value' }, reducers: { actionName: (state, action) => { // update state here } } }); export const { actionName } = sliceName.actions; export default sliceName.reducer;
createSlice creates a slice with state and actions together.
Reducers inside reducers define how state changes when actions run.
const counterSlice = createSlice({
name: 'counter',
initialState: { value: 0 },
reducers: {
increment: (state) => { state.value += 1; },
decrement: (state) => { state.value -= 1; }
}
});
export const { increment, decrement } = counterSlice.actions;
export default counterSlice.reducer;const todoSlice = createSlice({
name: 'todos',
initialState: [],
reducers: {
addTodo: (state, action) => { state.push(action.payload); },
removeTodo: (state, action) => {
return state.filter(todo => todo.id !== action.payload);
}
}
});
export const { addTodo, removeTodo } = todoSlice.actions;
export default todoSlice.reducer;This app shows a number that you can increase or decrease by pressing buttons. It uses a Redux slice to manage the number state.
import React from 'react'; import { View, Text, Button } from 'react-native'; import { configureStore } from '@reduxjs/toolkit'; import { Provider, useSelector, useDispatch } from 'react-redux'; import { createSlice } from '@reduxjs/toolkit'; const counterSlice = createSlice({ name: 'counter', initialState: { value: 0 }, reducers: { increment: (state) => { state.value += 1; }, decrement: (state) => { state.value -= 1; } } }); const store = configureStore({ reducer: counterSlice.reducer }); const Counter = () => { const count = useSelector(state => state.value); const dispatch = useDispatch(); return ( <View style={{ padding: 20, alignItems: 'center' }}> <Text style={{ fontSize: 24, marginBottom: 10 }}>Count: {count}</Text> <Button title="Increment" onPress={() => dispatch(counterSlice.actions.increment())} /> <View style={{ height: 10 }} /> <Button title="Decrement" onPress={() => dispatch(counterSlice.actions.decrement())} /> </View> ); }; export default function App() { return ( <Provider store={store}> <Counter /> </Provider> ); }
Reducers in createSlice can directly change state because Redux Toolkit uses a tool that handles immutability behind the scenes.
Always export actions and reducer from the slice to use them in your app.
Use useSelector to read state and useDispatch to send actions in React components.
Redux slices group state and actions for easier state management.
Actions are functions that describe how to change state.
Use slices to keep your app data organized and simple to update.
Practice
Solution
Step 1: Understand Redux slice role
A slice groups state and actions related to a feature in one place.Step 2: Compare with other options
Options A, C, and D are unrelated to state management.Final Answer:
To group related state and actions together for easier management -> Option DQuick Check:
Redux slice = group state and actions [OK]
- Confusing slices with UI components
- Thinking slices handle navigation
- Assuming slices style the app
Solution
Step 1: Recall createSlice syntax
Reducers are defined as functions with (state) parameter that mutate state directly.Step 2: Check each option
reducers: { increment: (state) => { state.value += 1 } } correctly uses reducers with state mutation. Options B and D wrongly use 'actions' key. reducers: { increment: () => state.value += 1 } uses arrow function without braces, which won't mutate state properly.Final Answer:
reducers: { increment: (state) => { state.value += 1 } } -> Option AQuick Check:
Reducers mutate state inside createSlice [OK]
- Using 'actions' instead of 'reducers' key
- Not mutating state directly inside reducer
- Returning new state instead of mutating
const counterSlice = createSlice({
name: 'counter',
initialState: { value: 0 },
reducers: {
increment: (state) => { state.value += 1 },
decrement: (state) => { state.value -= 1 }
}
});
const state = { value: 5 };
counterSlice.reducer(state, { type: 'counter/increment' });
console.log(state.value);What will be logged to the console?
Solution
Step 1: Understand reducer call
The reducer receives state { value: 5 } and action type 'counter/increment'. It runs increment reducer which adds 1 to state.value.Step 2: Calculate new state value
5 + 1 = 6, so state.value becomes 6.Final Answer:
6 -> Option AQuick Check:
Increment action adds 1 to value [OK]
- Thinking state is immutable and unchanged
- Confusing action type format
- Expecting error due to direct mutation
const todoSlice = createSlice({
name: 'todo',
initialState: [],
reducers: {
addTodo: (state, action) => {
state.push(action.payload);
}
}
});
// Later in component
dispatch(todoSlice.actions.addTodo('Buy milk'));What is the most likely reason the UI does not update?
Solution
Step 1: Check reducer code
The reducer correctly mutates state array by pushing new todo, which is allowed with Immer in createSlice.Step 2: Identify missing integration
If UI does not update, likely the slice reducer is not connected to the Redux store, so dispatch has no effect.Final Answer:
The slice reducer is not added to the store -> Option CQuick Check:
Reducer must be in store for dispatch to update state [OK]
- Thinking direct mutation is forbidden in createSlice
- Assuming initialState must be object
- Forgetting to add reducer to store
Solution
Step 1: Understand mutation in createSlice
Reducers can mutate state directly because Immer handles immutability internally.Step 2: Analyze each option
reducers: { updateName: (state, action) => { const user = state.find(u => u.id === action.payload.id); if(user) { user.name = action.payload.name; } } } finds user by id and mutates name directly, which is correct. reducers: { updateName: (state, action) => { state.map(u => u.id === action.payload.id ? { ...u, name: action.payload.name } : u); } } executes map but discards the new array without returning it or mutating state, incorrect. reducers: { updateName: (state, action) => { state = state.map(u => u.id === action.payload.id ? { ...u, name: action.payload.name } : u); } } tries to assign new array to state variable, which does not update state correctly. reducers: { updateName: (state, action) => { state.filter(u => u.id !== action.payload.id).push(action.payload); } } filters out user and pushes new one, which mutates array incorrectly and may cause bugs.Final Answer:
reducers: { updateName: (state, action) => { const user = state.find(u => u.id === action.payload.id); if(user) { user.name = action.payload.name; } } } -> Option BQuick Check:
Direct mutation with find and update is correct in createSlice [OK]
- Trying to reassign state variable inside reducer
- Using filter and push incorrectly
- Not mutating state directly in createSlice
Ready to prove it?
Pass the test and this pattern moves unknown
