12MahirPertemuan ke-12

State Management (Redux/Context)

Menerapkan state management dengan Redux atau Context API untuk aplikasi kompleks.

Topik Pembelajaran

  • Redux fundamentals (actions, reducers, store)
  • Redux Toolkit simplification
  • Redux middleware & thunks
  • Context API vs Redux trade-offs
  • Redux DevTools
  • Selectors & reselect
  • Async actions

Referensi & Sumber Daya

State Management (Context API & Redux)

Tujuan Pembelajaran

  • Memahami global state dengan Context API
  • Setup Redux Toolkit untuk state management
  • Membuat Todo App dengan Redux

A. Context API (Solusi Sederhana)

Buat Context untuk Theme

jsx
// context/ThemeContext.js import { createContext, useContext, useState } from 'react'; const ThemeContext = createContext(); export function ThemeProvider({ children }) { const [isDark, setIsDark] = useState(false); const toggle = () => setIsDark(!isDark); const theme = { isDark, toggle, colors: isDark ? { bg: '#1a1a1a', text: '#fff', card: '#2d2d2d' } : { bg: '#f5f5f5', text: '#000', card: '#fff' }, }; return ( <ThemeContext.Provider value={theme}> {children} </ThemeContext.Provider> ); } export const useTheme = () => useContext(ThemeContext);

Gunakan di Component

jsx
// App.js import { ThemeProvider, useTheme } from './context/ThemeContext'; import { View, Text, Switch, StyleSheet } from 'react-native'; function HomeScreen() { const { isDark, toggle, colors } = useTheme(); return ( <View style={[styles.container, { backgroundColor: colors.bg }]}> <Text style={{ color: colors.text, fontSize: 24 }}> Mode: {isDark ? 'Gelap' : 'Terang'} </Text> <Switch value={isDark} onValueChange={toggle} /> </View> ); } export default function App() { return ( <ThemeProvider> <HomeScreen /> </ThemeProvider> ); }

B. Redux Toolkit (Aplikasi Kompleks)

Install Redux

bash
npm install @reduxjs/toolkit react-redux

Buat Slice (store/todoSlice.js)

jsx
import { createSlice } from '@reduxjs/toolkit'; const todoSlice = createSlice({ name: 'todos', initialState: { items: [] }, reducers: { addTodo: (state, action) => { state.items.push({ id: Date.now().toString(), text: action.payload, done: false, }); }, toggleTodo: (state, action) => { const item = state.items.find(t => t.id === action.payload); if (item) item.done = !item.done; }, deleteTodo: (state, action) => { state.items = state.items.filter(t => t.id !== action.payload); }, }, }); export const { addTodo, toggleTodo, deleteTodo } = todoSlice.actions; export default todoSlice.reducer;

Setup Store (store/index.js)

jsx
import { configureStore } from '@reduxjs/toolkit'; import todoReducer from './todoSlice'; export const store = configureStore({ reducer: { todos: todoReducer }, });

Gunakan di App

jsx
import { Provider, useSelector, useDispatch } from 'react-redux'; import { store } from './store'; import { addTodo, toggleTodo, deleteTodo } from './store/todoSlice'; function TodoApp() { const todos = useSelector(state => state.todos.items); const dispatch = useDispatch(); const [text, setText] = useState(''); return ( <View style={{ flex: 1, padding: 20, paddingTop: 50 }}> <TextInput value={text} onChangeText={setText} placeholder="Tambah todo..." style={styles.input} /> <Button title="Tambah" onPress={() => { dispatch(addTodo(text)); setText(''); }} /> <FlatList data={todos} keyExtractor={i => i.id} renderItem={({ item }) => ( <TouchableOpacity onPress={() => dispatch(toggleTodo(item.id))} onLongPress={() => dispatch(deleteTodo(item.id))}> <Text style={{ textDecorationLine: item.done ? 'line-through' : 'none' }}> {item.text} </Text> </TouchableOpacity> )} /> </View> ); } export default function App() { return <Provider store={store}><TodoApp /></Provider>; }

C. Context vs Redux

  • Context API: Cocok untuk state sederhana (theme, auth, language)
  • Redux: Cocok untuk state kompleks (shopping cart, data besar)

D. Latihan Mandiri

  1. Implementasikan Theme toggle (dark/light) dengan Context API
  2. Buat Todo App dengan Redux Toolkit (add, toggle, delete)
  3. Gabungkan keduanya dalam satu aplikasi
  4. Screenshot dan kumpulkan source code