Si es un desarrollador, seguramente habrá escuchado la palabra Principios SOLID varias veces en su carrera de programación. En el desarrollo de software, el principio SOLID funciona como una guía para los desarrolladores. No importa qué idioma esté utilizando en su proyecto, para que su código sea limpio y fácil de mantener, debe aplicar el principio SOLID en su proyecto.
El principio SOLID facilita la tarea de los desarrolladores y también les ayuda a mantener el código en su proyecto. Hablemos ahora de React, un framework muy popular entre los desarrolladores.
Con la ayuda de React , puedes crear una interfaz de usuario hermosa. En la etapa inicial de su carrera, puede cometer muchos errores al escribir el código en React, pero una vez que tenga experiencia trabajando en él, comprenderá que también es importante escribir un código limpio y mantenible en React. Por eso, seguro que algo que te puede ayudar es el principio SOLID.
Puede escribir componentes React pequeños, hermosos y limpios. El principio SOLID hace que su componente sea visible con responsabilidades claras. El principio SOLID nos dice que cada clase debe tener un solo propósito de existencia. En React, los componentes deben hacer solo una cosa a la vez.
Ahora comprendamos cómo refactorizar un código incorrecto en React y hacerlo más limpio. Primero, consideremos un mal ejemplo …
Javascript
import React, {useEffect, useReducer, useState} from "react"; const initialState = { isLoading: true }; // COMPLEX STATE MANAGEMENT function reducer(state, action) { switch (action.type) { case 'LOADING': return {isLoading: true}; case 'FINISHED': return {isLoading: false}; default: return state; } } export const SingleResponsibilityPrinciple = () => { const [users , setUsers] = useState([]) const [filteredUsers , setFilteredUsers] = useState([]) const [state, dispatch] = useReducer(reducer, initialState); const showDetails = (userId) => { const user = filteredUsers.find(user => user.id===userId); alert(user.contact) } // REMOTE DATA FETCHING useEffect(() => { dispatch({type:'LOADING'}) fetch('https://jsonplaceholder.typicode.com/users') .then(response => response.json()) .then(json => { dispatch({type:'FINISHED'}) setUsers(json) }) },[]) // PROCESSING DATA useEffect(() => { const filteredUsers = users.map(user => { return { id: user.id, name: user.name, contact: `${user.phone} , ${user.email}` }; }); setFilteredUsers(filteredUsers) },[users]) // COMPLEX UI RENDERING return <> <div> Users List</div> <div> Loading state: {state.isLoading? 'Loading': 'Success'}</div> {users.map(user => { return <div key={user.id} onClick={() => showDetails(user.id)}> <div>{user.name}</div> <div>{user.email}</div> </div> })} </> }
Aquí, estamos obteniendo los datos de la fuente remota y luego los estamos representando en la interfaz de usuario. También estamos detectando el estado de carga de la llamada API. Básicamente, el código anterior se divide principalmente en… cuatro cosas…
- Obtención remota de datos…
- Filtrado de datos…
- Gestión estatal compleja…
- Funcionalidad de interfaz de usuario compleja…
Ahora veamos cómo mejorar el diseño de este código y cómo hacerlo más fácil de limpiar…
1. Separación de la lógica de procesamiento de datos del código.
Nunca debe mantener sus llamadas HTTP dentro del componente. Esta es una regla general básica. Para eliminar estos códigos del componente, puede seguir varias estrategias.
Puede crear un gancho personalizado y puede mover su lógica de obtención y filtrado de datos dentro de ese gancho personalizado. Veamos cómo hacer esto…
Cree un gancho llamado useGetRemoteData. Se parece a continuación…
Javascript
import {useEffect, useReducer, useState} from "react"; const initialState = { isLoading: true }; function reducer(state, action) { switch (action.type) { case 'LOADING': return {isLoading: true}; case 'FINISHED': return {isLoading: false}; default: return state; } } export const useGetRemoteData = (url) => { const [users , setUsers] = useState([]) const [state, dispatch] = useReducer(reducer, initialState); const [filteredUsers , setFilteredUsers] = useState([]) useEffect(() => { dispatch({type:'LOADING'}) fetch('https://jsonplaceholder.typicode.com/users') .then(response => response.json()) .then(json => { dispatch({type:'FINISHED'}) setUsers(json) }) },[]) useEffect(() => { const filteredUsers = users.map(user => { return { id: user.id, name: user.name, contact: `${user.phone} , ${user.email}` }; }); setFilteredUsers(filteredUsers) },[users]) return {filteredUsers , isLoading: state.isLoading} }
Ahora, si observa su componente principal, se verá así…
Javascript
import React from "react"; import {useGetRemoteData} from "./useGetRemoteData"; export const SingleResponsibilityPrinciple = () => { const {filteredUsers , isLoading} = useGetRemoteData() const showDetails = (userId) => { const user = filteredUsers.find(user => user.id===userId); alert(user.contact) } return <> <div> Users List</div> <div> Loading state: {isLoading? 'Loading': 'Success'}</div> {filteredUsers.map(user => { return <div key={user.id} onClick={() => showDetails(user.id)}> <div>{user.name}</div> <div>{user.email}</div> </div> })} </> }
Puede observar que su componente es mucho más limpio y fácil de entender ahora. Hagamos nuestro código mucho mejor usando algunas técnicas o métodos más.
2. Separe el código de obtención de datos para que sea reutilizable
useGetRemoteData tiene dos propósitos en su código…
- Obtener datos de una fuente remota
- Filtrado de datos
Podemos hacer un enlace separado y podemos mover nuestra lógica de obtención de datos allí. Démosle el nombre…useHttpGetRequest. Toma la URL como un componente.
Javascript
import {useEffect, useReducer, useState} from "react"; import {loadingReducer} from "./LoadingReducer"; const initialState = { isLoading: true }; export const useHttpGetRequest = (URL) => { const [users , setUsers] = useState([]) const [state, dispatch] = useReducer(loadingReducer, initialState); useEffect(() => { dispatch({type:'LOADING'}) fetch(URL) .then(response => response.json()) .then(json => { dispatch({type:'FINISHED'}) setUsers(json) }) },[]) return {users , isLoading: state.isLoading} }
También separemos la lógica del reductor en un archivo separado…
Javascript
export function loadingReducer(state, action) { switch (action.type) { case 'LOADING': return {isLoading: true}; case 'FINISHED': return {isLoading: false}; default: return state; } }
Después de realizar las dos operaciones anteriores… useGetRemoteData se ve a continuación…
Javascript
import {useEffect, useState} from "react"; import {useHttpGetRequest} from "./useHttpGet"; const REMOTE_URL = 'https://jsonplaceholder.typicode.com/users' export const useGetRemoteData = () => { const {users , isLoading} = useHttpGetRequest(REMOTE_URL) const [filteredUsers , setFilteredUsers] = useState([]) useEffect(() => { const filteredUsers = users.map(user => { return { id: user.id, name: user.name, contact: `${user.phone} , ${user.email}` }; }); setFilteredUsers(filteredUsers) },[users]) return {filteredUsers , isLoading} }
Ahora puedes observar que el código se vuelve mucho más limpio. Podemos realizar algunas operaciones más y hacer que este código sea mucho mejor. Veamos cómo hacer esto…
3. Descomponer los componentes de la interfaz de usuario
Separe el código de los detalles del usuario en un componente diferente que solo sea responsable de mostrar los detalles del usuario.
Javascript
const UserDetails = (user) => { const showDetails = (user) => { alert(user.contact) } return <div key={user.id} onClick={() => showDetails(user)}> <div>{user.name}</div> <div>{user.email}</div> </div> }
Ahora el componente original se ve a continuación:
Javascript
import React from "react"; import {useGetRemoteData} from "./useGetRemoteData"; export const Users = () => { const {filteredUsers , isLoading} = useGetRemoteData() return <> <div> Users List</div> <div> Loading state: {isLoading? 'Loading': 'Success'}</div> {filteredUsers.map(user => <UserDetails user={user}/>)} </> }
¿Observó que su código, que era demasiado largo, ahora es demasiado corto? Simplemente descomponemos el código en cinco componentes separados y colocamos nuestra lógica allí. Cada componente es ahora responsable de una sola responsabilidad.
Revisemos nuestro código y veamos qué hicimos aquí. Creamos cinco componentes diferentes…
- Users.js: Responsable de mostrar la lista de usuarios.
- Detalles de usuario.js:
- useGetRemoteData.js: Responsable de filtrar datos remotos
- useHttpGetrequest.js: responsable de las llamadas HTTP
- LoadingReducer.js: gestión de estados complejos.
Espero que las cosas te queden claras ahora.
Publicación traducida automáticamente
Artículo escrito por anuupadhyay y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA