State Management dengan Redux/Context API
Implementasi Redux
20. Setup Redux dalam React Native
Install dependencies dan setup store provider di root aplikasi.
import { configureStore } from "@reduxjs/toolkit";
import counterReducer from "./counterSlice";
export const store = configureStore({
reducer: {
counter: counterReducer,
},
});
import { Provider } from "react-redux";
import { store } from "./store";
export default function App() {
return (
<Provider store={store}>
<MainApp />
</Provider>
);
}
21. Membuat Actions dan Action Creators
Action creators adalah fungsi yang mengembalikan action object untuk memudahkan pembuatan action.
const INCREMENT = "INCREMENT";
const DECREMENT = "DECREMENT";
const INCREMENT_BY_AMOUNT = "INCREMENT_BY_AMOUNT";
function increment() {
return { type: INCREMENT };
}
function decrement() {
return { type: DECREMENT };
}
function incrementByAmount(amount) {
return {
type: INCREMENT_BY_AMOUNT,
payload: amount,
};
}
dispatch(increment());
dispatch(incrementByAmount(5));
function addTodo(text) {
return {
type: "ADD_TODO",
payload: {
id: Date.now(),
text: text,
completed: false,
},
};
}
22. Membuat Reducers
Reducer menangani berbagai action types dan mengubah state sesuai logika bisnis.
const initialState = {
value: 0,
status: "idle",
};
function counterReducer(state = initialState, action) {
switch (action.type) {
case "INCREMENT":
return {
...state,
value: state.value + 1,
};
case "DECREMENT":
return {
...state,
value: state.value - 1,
};
case "INCREMENT_BY_AMOUNT":
return {
...state,
value: state.value + action.payload,
};
case "RESET":
return initialState;
default:
return state;
}
}
export default counterReducer;
23. Menggabungkan Multiple Reducers (combineReducers)
combineReducers menggabungkan beberapa reducer menjadi satu root reducer.
import { combineReducers } from "redux";
function userReducer(state = null, action) {
switch (action.type) {
case "LOGIN":
return action.payload;
case "LOGOUT":
return null;
default:
return state;
}
}
function todosReducer(state = [], action) {
switch (action.type) {
case "ADD_TODO":
return [...state, action.payload];
default:
return state;
}
}
const rootReducer = combineReducers({
user: userReducer,
todos: todosReducer,
counter: counterReducer,
});
24. Konfigurasi Store
Store dikonfigurasi dengan root reducer dan optional middleware.
import { createStore, applyMiddleware } from "redux";
import { configureStore } from "@reduxjs/toolkit";
import rootReducer from "./reducers";
const store = createStore(rootReducer);
export const store = configureStore({
reducer: {
user: userReducer,
todos: todosReducer,
counter: counterReducer,
},
middleware: (getDefaultMiddleware) =>
getDefaultMiddleware({
serializableCheck: false,
}),
});
export default store;
25. Menggunakan Provider dari react-redux
Provider component membuat Redux store tersedia untuk seluruh aplikasi.
import React from "react";
import { Provider } from "react-redux";
import { store } from "./store";
import { NavigationContainer } from "@react-navigation/native";
import MainNavigator from "./navigation/MainNavigator";
export default function App() {
return (
<Provider store={store}>
<NavigationContainer>
<MainNavigator />
</NavigationContainer>
</Provider>
);
}
26. Mengakses State dengan useSelector
useSelector hook mengambil data dari Redux store berdasarkan selector function.
import { useSelector } from "react-redux";
function CounterScreen() {
const count = useSelector((state) => state.counter.value);
const status = useSelector((state) => state.counter.status);
const user = useSelector((state) => state.user);
const userName = useSelector((state) => state.user?.name);
const todos = useSelector((state) => state.todos);
const completedTodos = useSelector((state) =>
state.todos.filter((todo) => todo.completed)
);
return (
<View>
<Text>Count: {count}</Text>
<Text>Status: {status}</Text>
<Text>User: {userName}</Text>
<Text>Completed: {completedTodos.length}</Text>
</View>
);
}
27. Dispatch Actions dengan useDispatch
useDispatch hook mengembalikan dispatch function untuk mengirim actions.
import { useDispatch, useSelector } from "react-redux";
import { Button, View, Text } from "react-native";
function CounterScreen() {
const dispatch = useDispatch();
const count = useSelector((state) => state.counter.value);
const handleIncrement = () => {
dispatch({ type: "INCREMENT" });
};
const handleDecrement = () => {
dispatch({ type: "DECREMENT" });
};
const handleIncrementByAmount = () => {
dispatch({
type: "INCREMENT_BY_AMOUNT",
payload: 5,
});
};
const handleReset = () => {
dispatch({ type: "RESET" });
};
return (
<View>
<Text>Count: {count}</Text>
<Button title="+" onPress={handleIncrement} />
<Button title="-" onPress={handleDecrement} />
<Button title="+5" onPress={handleIncrementByAmount} />
<Button title="Reset" onPress={handleReset} />
</View>
);
}