React I Redux Praktyczne Tworzenie Aplikacji Www

Wyobraź sobie, że chcesz zbudować dynamiczną, responsywną aplikację webową. Chcesz, żeby była szybka, łatwa w utrzymaniu i skalowalna. Potrzebujesz solidnego fundamentu, a React i Redux to duet, który idealnie spełnia te wymagania. Ten artykuł jest dedykowany programistom, którzy chcą praktycznie nauczyć się łączyć React z Reduxem, aby tworzyć zaawansowane aplikacje internetowe.
Wprowadzenie do React i Redux
Zanim zanurzymy się w kodzie, poświęćmy chwilę na zrozumienie, czym właściwie są React i Redux i dlaczego warto ich używać razem.
React: Biblioteka do budowania interfejsów użytkownika
React to biblioteka JavaScript stworzona przez Facebook, służąca do budowania interfejsów użytkownika (UI). Jej główne zalety to:
Must Read
- Komponentyzacja: UI jest podzielony na niezależne, wielokrotnego użytku komponenty. Ułatwia to zarządzanie kodem, testowanie i rozbudowę aplikacji.
- Virtual DOM: React wykorzystuje Virtual DOM, co sprawia, że aktualizacje interfejsu są bardzo szybkie i wydajne. Zamiast bezpośrednio manipulować DOM, React aktualizuje Virtual DOM, a następnie znajduje minimalną liczbę zmian potrzebnych do zastosowania w rzeczywistym DOM.
- Deklaratywność: Opisujesz, jak interfejs ma wyglądać dla danego stanu danych, a React zajmuje się aktualizacją DOM. To upraszcza logikę i sprawia, że kod jest bardziej czytelny.
- JSX: Pozwala na pisanie kodu HTML w JavaScript, co ułatwia wizualizację struktury komponentów.
Redux: Zarządzanie stanem aplikacji
Redux to biblioteka do zarządzania stanem aplikacji. Jest szczególnie przydatna w dużych, złożonych aplikacjach, gdzie wiele komponentów musi współdzielić i aktualizować dane. Redux wprowadza następujące koncepcje:
- Store: Pojedyncze źródło prawdy, przechowujące cały stan aplikacji.
- Actions: Zdarzenia opisujące, co się stało w aplikacji (np. "DODAJ_PRODUKT", "POBIERZ_DANE").
- Reducers: Funkcje, które na podstawie akcji i aktualnego stanu generują nowy stan. Reducer to czysta funkcja - co oznacza, że dla tych samych argumentów zawsze zwraca tę samą wartość i nie ma efektów ubocznych.
- Dispatch: Funkcja, która wysyła akcje do store.
- Subscribe: Mechanizm pozwalający komponentom na subskrypcję zmian w stanie i aktualizację interfejsu.
Dlaczego łączyć React z Reduxem? React radzi sobie świetnie z budowaniem interfejsów, ale w większych aplikacjach zarządzanie stanem tylko za pomocą React może stać się skomplikowane. Redux centralizuje stan, ułatwia debugowanie i testowanie oraz promuje spójność w całej aplikacji.
Budujemy prostą aplikację: Lista zadań (Todo)
Aby pokazać, jak React i Redux działają w praktyce, zbudujemy prostą aplikację: listę zadań (Todo). Będzie ona umożliwiała dodawanie, oznaczanie jako wykonane i usuwanie zadań.
Krok 1: Konfiguracja środowiska
Zaczynamy od stworzenia nowego projektu React:

npx create-react-app todo-app
cd todo-app
Następnie instalujemy Redux oraz biblioteki `react-redux` i `redux-thunk`:
npm install redux react-redux redux-thunk
Redux Thunk to middleware, który pozwala na wykonywanie asynchronicznych akcji (np. pobieranie danych z API) w Redux. Będzie nam potrzebny, jeśli w przyszłości będziemy chcieli rozszerzyć naszą aplikację o pobieranie zadań z serwera.
Krok 2: Definiowanie akcji
Tworzymy katalog `src/actions` i dodajemy plik `todosActions.js` z następującymi akcjami:
// src/actions/todosActions.js
export const ADD_TODO = 'ADD_TODO';
export const TOGGLE_TODO = 'TOGGLE_TODO';
export const DELETE_TODO = 'DELETE_TODO';
export const addTodo = (text) => ({
type: ADD_TODO,
payload: {
text,
},
});
export const toggleTodo = (id) => ({
type: TOGGLE_TODO,
payload: {
id,
},
});
export const deleteTodo = (id) => ({
type: DELETE_TODO,
payload: {
id,
},
});
Każda akcja ma typ (type) i opcjonalny ładunek (payload) z danymi.
Krok 3: Definiowanie Reducera
Tworzymy katalog `src/reducers` i dodajemy plik `todosReducer.js` z reducerem:

// src/reducers/todosReducer.js
import { ADD_TODO, TOGGLE_TODO, DELETE_TODO } from '../actions/todosActions';
const initialState = {
todos: [],
};
const todosReducer = (state = initialState, action) => {
switch (action.type) {
case ADD_TODO:
return {
...state,
todos: [
...state.todos,
{
id: Date.now(),
text: action.payload.text,
completed: false,
},
],
};
case TOGGLE_TODO:
return {
...state,
todos: state.todos.map((todo) =>
todo.id === action.payload.id ? { ...todo, completed: !todo.completed } : todo
),
};
case DELETE_TODO:
return {
...state,
todos: state.todos.filter((todo) => todo.id !== action.payload.id),
};
default:
return state;
}
};
export default todosReducer;
Reducer przyjmuje aktualny stan i akcję, a następnie na podstawie typu akcji zwraca nowy stan. Pamiętaj: reducer musi być czystą funkcją.
Krok 4: Konfiguracja Store
Tworzymy plik `src/store.js` i konfigurujemy store Redux:
// src/store.js
import { createStore, applyMiddleware, combineReducers } from 'redux';
import thunk from 'redux-thunk';
import todosReducer from './reducers/todosReducer';
const rootReducer = combineReducers({
todos: todosReducer,
});
const store = createStore(rootReducer, applyMiddleware(thunk));
export default store;
Używamy `combineReducers` do połączenia wielu reducerów (w tym przypadku tylko `todosReducer`). Dodajemy `redux-thunk` jako middleware, aby umożliwić asynchroniczne akcje.
Krok 5: Tworzenie komponentów React
Tworzymy komponenty React, które będą łączyły się ze store Redux. Zaczynamy od komponentu `TodoList.js`:
// src/components/TodoList.js
import React from 'react';
import { connect } from 'react-redux';
import { toggleTodo, deleteTodo } from '../actions/todosActions';
const TodoList = ({ todos, toggleTodo, deleteTodo }) => {
return (
<ul>
{todos.map((todo) => (
<li key={todo.id}>
<span style={{ textDecoration: todo.completed ? 'line-through' : 'none' }} onClick={() => toggleTodo(todo.id)}>
{todo.text}
</span>
<button onClick={() => deleteTodo(todo.id)}>Usuń</button>
</li>
))}
</ul>
);
};
const mapStateToProps = (state) => ({
todos: state.todos.todos,
});
const mapDispatchToProps = {
toggleTodo,
deleteTodo,
};
export default connect(mapStateToProps, mapDispatchToProps)(TodoList);
Komponent `TodoList` wyświetla listę zadań. Używamy `connect` z `react-redux` do połączenia komponentu ze store Redux. `mapStateToProps` pobiera dane ze store i przekazuje je jako propsy do komponentu. `mapDispatchToProps` mapuje akcje Redux na propsy komponentu, umożliwiając wywoływanie akcji bezpośrednio z komponentu.

Następnie tworzymy komponent `TodoForm.js`, który umożliwia dodawanie nowych zadań:
// src/components/TodoForm.js
import React, { useState } from 'react';
import { connect } from 'react-redux';
import { addTodo } from '../actions/todosActions';
const TodoForm = ({ addTodo }) => {
const [text, setText] = useState('');
const handleSubmit = (e) => {
e.preventDefault();
if (text.trim()) {
addTodo(text);
setText('');
}
};
return (
<form onSubmit={handleSubmit}>
<input type="text" value={text} onChange={(e) => setText(e.target.value)} />
<button type="submit">Dodaj</button>
</form>
);
};
const mapDispatchToProps = {
addTodo,
};
export default connect(null, mapDispatchToProps)(TodoForm);
Komponent `TodoForm` zawiera formularz do wprowadzania tekstu zadania. Używamy `useState` do zarządzania stanem inputa. Podobnie jak w `TodoList`, używamy `connect` i `mapDispatchToProps` do połączenia komponentu ze store Redux.
Krok 6: Łączenie komponentów w App.js
W pliku `src/App.js` łączymy komponenty `TodoList` i `TodoForm`:
// src/App.js
import React from 'react';
import TodoList from './components/TodoList';
import TodoForm from './components/TodoForm';
import { Provider } from 'react-redux';
import store from './store';
function App() {
return (
<Provider store={store}>
<div className="App">
<h1>Lista Zadań</h1>
<TodoForm />
<TodoList />
</div>
</Provider>
);
}
export default App;
Kluczowe jest użycie komponentu `Provider` z `react-redux` aby udostępnić store całej aplikacji. Owijamy całą aplikację w `Provider` i przekazujemy store jako prop.
Krok 7: Uruchomienie aplikacji
Uruchamiamy aplikację:

npm start
Gratulacje! Właśnie stworzyłeś prostą aplikację Todo z użyciem React i Redux. Możesz dodawać zadania, oznaczać je jako wykonane i usuwać je.
Podsumowanie i dalsze kroki
W tym artykule pokazaliśmy, jak używać React i Redux do budowania aplikacji webowych. Zaczęliśmy od wprowadzenia do React i Redux, a następnie krok po kroku zbudowaliśmy prostą aplikację Todo.
Pamiętaj: To dopiero początek! Możesz rozszerzyć tę aplikację o:
- Pobieranie zadań z API (wykorzystując
redux-thunk) - Filtrowanie zadań (np. wyświetlanie tylko zadań niezakończonych)
- Persystencję danych (zapisywanie zadań w localStorage lub bazie danych)
- Dodawanie testów jednostkowych
Kluczem do opanowania React i Redux jest praktyka. Eksperymentuj z kodem, buduj własne aplikacje i szukaj inspiracji w internecie. Istnieje wiele darmowych kursów i tutoriali, które mogą pomóc Ci w dalszej nauce. Powodzenia!
Zachęcamy do dalszego eksplorowania możliwości tych bibliotek. Im więcej będziesz ćwiczyć, tym szybciej zobaczysz, jak potężne i elastyczne narzędzia oferują React i Redux. Życzymy powodzenia w tworzeniu wspaniałych aplikacji!
