En aquest tema, aprendrem com gestionar l'estat de la nostra aplicació React i com integrar una API per obtenir i enviar dades. Aquest és un pas crucial per construir aplicacions React completes i funcionals.
Objectius del tema
- Comprendre com gestionar l'estat global de l'aplicació.
- Aprendre a utilitzar Redux per a la gestió de l'estat.
- Integrar una API RESTful amb React.
- Gestionar les sol·licituds HTTP i el cicle de vida de les dades.
- Configuració de Redux
Instal·lació de Redux i React-Redux
Primer, necessitem instal·lar les biblioteques necessàries per utilitzar Redux amb React.
Creació de l'estructura de Redux
1.1. Creació de l'Store
L'Store és on es guarda l'estat global de l'aplicació.
// src/store/index.js import { createStore } from 'redux'; import rootReducer from '../reducers'; const store = createStore(rootReducer); export default store;
1.2. Creació del Reducer
El Reducer és una funció que especifica com canvia l'estat de l'aplicació en resposta a una acció.
// src/reducers/index.js const initialState = { data: [], loading: false, error: null, }; const rootReducer = (state = initialState, action) => { switch (action.type) { case 'FETCH_DATA_REQUEST': return { ...state, loading: true, error: null }; case 'FETCH_DATA_SUCCESS': return { ...state, loading: false, data: action.payload }; case 'FETCH_DATA_FAILURE': return { ...state, loading: false, error: action.error }; default: return state; } }; export default rootReducer;
1.3. Proveïdor de Redux
Per connectar Redux amb React, utilitzem el proveïdor de React-Redux.
// src/index.js import React from 'react'; import ReactDOM from 'react-dom'; import { Provider } from 'react-redux'; import store from './store'; import App from './App'; ReactDOM.render( <Provider store={store}> <App /> </Provider>, document.getElementById('root') );
- Integració de l'API
2.1. Creació de les Accions
Les accions són objectes que descriuen el tipus d'esdeveniment que ha ocorregut i les dades necessàries per actualitzar l'estat.
// src/actions/index.js export const fetchDataRequest = () => ({ type: 'FETCH_DATA_REQUEST', }); export const fetchDataSuccess = (data) => ({ type: 'FETCH_DATA_SUCCESS', payload: data, }); export const fetchDataFailure = (error) => ({ type: 'FETCH_DATA_FAILURE', error, }); export const fetchData = () => { return (dispatch) => { dispatch(fetchDataRequest()); fetch('https://api.example.com/data') .then((response) => response.json()) .then((data) => dispatch(fetchDataSuccess(data))) .catch((error) => dispatch(fetchDataFailure(error))); }; };
2.2. Utilització de Thunk Middleware
Per gestionar accions asíncrones, utilitzem redux-thunk
.
// src/store/index.js import { createStore, applyMiddleware } from 'redux'; import thunk from 'redux-thunk'; import rootReducer from '../reducers'; const store = createStore(rootReducer, applyMiddleware(thunk)); export default store;
2.3. Connectar el Component a Redux
Finalment, connectem el component a Redux per accedir a l'estat i les accions.
// src/components/DataComponent.js import React, { useEffect } from 'react'; import { useSelector, useDispatch } from 'react-redux'; import { fetchData } from '../actions'; const DataComponent = () => { const dispatch = useDispatch(); const { data, loading, error } = useSelector((state) => state); useEffect(() => { dispatch(fetchData()); }, [dispatch]); if (loading) return <p>Loading...</p>; if (error) return <p>Error: {error}</p>; return ( <div> <h1>Data</h1> <ul> {data.map((item) => ( <li key={item.id}>{item.name}</li> ))} </ul> </div> ); }; export default DataComponent;
Exercici Pràctic
Objectiu
Crear una aplicació que mostri una llista d'usuaris obtinguts d'una API i permeti afegir nous usuaris.
Passos
- Configura Redux: Crea l'Store, el Reducer i les Accions necessàries.
- Integra l'API: Utilitza
fetch
per obtenir dades d'una API i actualitzar l'estat de l'aplicació. - Crea el Component: Crea un component que mostri la llista d'usuaris i un formulari per afegir nous usuaris.
Solució
// src/actions/index.js export const addUser = (user) => ({ type: 'ADD_USER', payload: user, }); export const fetchUsers = () => { return (dispatch) => { dispatch(fetchDataRequest()); fetch('https://api.example.com/users') .then((response) => response.json()) .then((data) => dispatch(fetchDataSuccess(data))) .catch((error) => dispatch(fetchDataFailure(error))); }; }; // src/reducers/index.js const initialState = { users: [], loading: false, error: null, }; const rootReducer = (state = initialState, action) => { switch (action.type) { case 'FETCH_DATA_REQUEST': return { ...state, loading: true, error: null }; case 'FETCH_DATA_SUCCESS': return { ...state, loading: false, users: action.payload }; case 'FETCH_DATA_FAILURE': return { ...state, loading: false, error: action.error }; case 'ADD_USER': return { ...state, users: [...state.users, action.payload] }; default: return state; } }; export default rootReducer; // src/components/UserComponent.js import React, { useState, useEffect } from 'react'; import { useSelector, useDispatch } from 'react-redux'; import { fetchUsers, addUser } from '../actions'; const UserComponent = () => { const dispatch = useDispatch(); const { users, loading, error } = useSelector((state) => state); const [name, setName] = useState(''); useEffect(() => { dispatch(fetchUsers()); }, [dispatch]); const handleAddUser = () => { const newUser = { id: users.length + 1, name }; dispatch(addUser(newUser)); setName(''); }; if (loading) return <p>Loading...</p>; if (error) return <p>Error: {error}</p>; return ( <div> <h1>Users</h1> <ul> {users.map((user) => ( <li key={user.id}>{user.name}</li> ))} </ul> <input type="text" value={name} onChange={(e) => setName(e.target.value)} placeholder="Add a new user" /> <button onClick={handleAddUser}>Add User</button> </div> ); }; export default UserComponent;
Resum
En aquest tema, hem après a gestionar l'estat global de l'aplicació amb Redux i a integrar una API per obtenir i enviar dades. Hem vist com configurar Redux, crear accions i reducers, i connectar els components de React a l'estat global. També hem practicat aquests conceptes amb un exercici pràctic. Ara estem preparats per avançar cap a temes més avançats en React.
Curs de React
Mòdul 1: Introducció a React
- Què és React?
- Configuració de l'entorn de desenvolupament
- Hola Món en React
- JSX: Extensió de la sintaxi de JavaScript
Mòdul 2: Components de React
- Comprendre els components
- Components funcionals vs components de classe
- Props: Passar dades als components
- State: Gestionar l'estat del component
Mòdul 3: Treballar amb esdeveniments
- Gestionar esdeveniments en React
- Renderització condicional
- Llistes i claus
- Formularis i components controlats
Mòdul 4: Conceptes avançats de components
- Elevar l'estat
- Composició vs herència
- Mètodes del cicle de vida de React
- Hooks: Introducció i ús bàsic
Mòdul 5: Hooks de React
Mòdul 6: Enrutament en React
Mòdul 7: Gestió de l'estat
- Introducció a la gestió de l'estat
- API de context
- Redux: Introducció i configuració
- Redux: Accions i reductors
- Redux: Connexió amb React
Mòdul 8: Optimització del rendiment
- Tècniques d'optimització del rendiment de React
- Memorització amb React.memo
- Hooks useMemo i useCallback
- Divisió de codi i càrrega mandrosa
Mòdul 9: Proves en React
- Introducció a les proves
- Proves unitàries amb Jest
- Proves de components amb React Testing Library
- Proves de punta a punta amb Cypress
Mòdul 10: Temes avançats
- Renderització del costat del servidor (SSR) amb Next.js
- Generació de llocs estàtics (SSG) amb Next.js
- TypeScript amb React
- React Native: Construir aplicacions mòbils