Uso de componentes funcionales
- Utiliza componentes funcionales siempre que sea posible. Son más concisos y permiten el uso de hooks.
- JSX: Usa JSX para describir la UI. Es más legible y fácil de mantener.
// Componente Funcional const MyComponent = () => { return <div>Hello World</div>; };
Pasar Parámetros (Props)
- Padre a Hijo: Para pasar datos de un componente padre a uno hijo, usa props.
- Hijo a Padre: Para comunicar datos de hijo a padre, pasa una función como prop.
// Componente Padre const ParentComponent = () => { const [data, setData] = useState("Initial Data"); const handleDataChange = (newData) => { setData(newData); }; return <ChildComponent data={data} onDataChange={handleDataChange} />; }; // Componente Hijo const ChildComponent = ({ data, onDataChange }) => { return ( <div> <p>{data}</p> <button onClick={() => onDataChange("New Data")}>Change Data</button> </div> ); };
Uso de Hooks
- useState: Para manejar estados en componentes funcionales.
const [state, setState] = useState(initialState);
- useEffect: Para manejar efectos secundarios, como fetch de datos, suscripciones, o cambios en el DOM. Es el equivalente a
componentDidMount
,componentDidUpdate
ycomponentWillUnmount
.
useEffect(() => { // Código a ejecutar cuando el componente se monta o el estado/props cambian. return () => { // Cleanup opcional }; }, [dependencies]); // Si dependencies está vacío, se ejecuta solo al montar y desmontar.
- useMemo: Para memorizar valores calculados y evitar recalculaciones costosas en cada renderizado.
const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);
- useCallback: Para memorizar funciones y evitar re-creaciones en cada renderizado, útil al pasar callbacks a componentes hijos.
const memoizedCallback = useCallback(() => { doSomething(a, b); }, [a, b]);
- Encapsulación de Lógica: Crea hooks personalizados para reutilizar lógica en diferentes componentes.
const useCustomHook = (initialValue) => { const [value, setValue] = useState(initialValue); const updateValue = (newValue) => { setValue(newValue); }; return [value, updateValue]; }; const MyComponent = () => { const [value, setValue] = useCustomHook('Initial Value'); return ( <div> <p>{value}</p> <button onClick={() => setValue('New Value')}>Change Value</button> </div> ); };
Enrutamiento
- Usa
react-router-dom
para manejar el enrutamiento en tu aplicación.
import { BrowserRouter as Router, Route, Switch, Link } from 'react-router-dom'; const App = () => { return ( <Router> <nav> <Link to="/">Home</Link> <Link to="/about">About</Link> </nav> <Switch> <Route exact path="/" component={Home} /> <Route path="/about" component={About} /> </Switch> </Router> ); };
Reutilización
- Separación de Componentes: Divide tu aplicación en componentes pequeños y reutilizables.
- Hooks Personalizados: Si tienes lógica repetitiva, considera crear hooks personalizados.
const useCustomHook = (initialValue) => { const [value, setValue] = useState(initialValue); const updateValue = (newValue) => { setValue(newValue); }; return [value, updateValue]; };
Optimización rendimiento
const MemoizedComponent = React.memo(({ prop }) => { // Render logic });
Uso de estados globales
- Context API: Para estados globales o compartir datos entre múltiples componentes sin pasar props por muchos niveles.
import React, { createContext, useContext, useState } from 'react'; // Crear el contexto const MyContext = createContext(); const MyProvider = ({ children }) => { const [state, setState] = useState('Initial State'); return ( <MyContext.Provider value={{ state, setState }}> {children} </MyContext.Provider> ); }; const MyComponent = () => { const { state, setState } = useContext(MyContext); return ( <div> <p>{state}</p> <button onClick={() => setState('New State')}>Change State</button> </div> ); }; // Usar el proveedor en el árbol de componentes const App = () => ( <MyProvider> <MyComponent /> </MyProvider> );
- Redux: Para aplicaciones más complejas con manejo de estado global más avanzado.
import { createStore } from 'redux'; import { Provider, useDispatch, useSelector } from 'react-redux'; const initialState = { value: 0 }; // Reducer const reducer = (state = initialState, action) => { switch (action.type) { case 'INCREMENT': return { ...state, value: state.value + 1 }; default: return state; } }; // Crear el store const store = createStore(reducer); const Counter = () => { const dispatch = useDispatch(); const value = useSelector((state) => state.value); return ( <div> <p>{value}</p> <button onClick={() => dispatch({ type: 'INCREMENT' })}>Increment</button> </div> ); }; // Usar el proveedor de Redux en el árbol de componentes const App = () => ( <Provider store={store}> <Counter /> </Provider> );
Suspense y Code Splitting
- React.lazy y Suspense: Para carga diferida de componentes, mejorando el rendimiento de la aplicación.
import { Formik, Form, Field, ErrorMessage } from 'formik'; import * as Yup from 'yup'; const MyForm = () => { return ( <Formik initialValues={{ name: '' }} validationSchema={Yup.object({ name: Yup.string().required('Required'), })} onSubmit={(values) => { console.log(values); }} > <Form> <Field name="name" type="text" /> <ErrorMessage name="name" /> <button type="submit">Submit</button> </Form> </Formik> ); };
Formularios
- Controlled Components: Manejar los formularios mediante estados de React.
const MyForm = () => { const [value, setValue] = useState(''); const handleChange = (e) => setValue(e.target.value); const handleSubmit = (e) => { e.preventDefault(); console.log(value); }; return ( <form onSubmit={handleSubmit}> <input type="text" value={value} onChange={handleChange} /> <button type="submit">Submit</button> </form> ); };
- Libraries: Usar librerías como
Formik
yYup
para simplificar el manejo y validación de formularios.
import { Formik, Form, Field, ErrorMessage } from 'formik'; import * as Yup from 'yup'; const MyForm = () => { return ( <Formik initialValues={{ name: '' }} validationSchema={Yup.object({ name: Yup.string().required('Required'), })} onSubmit={(values) => { console.log(values); }} > <Form> <Field name="name" type="text" /> <ErrorMessage name="name" /> <button type="submit">Submit</button> </Form> </Formik> ); };
Manejo de Errores
- Error Boundaries: Para capturar errores en componentes hijos y mostrar una UI de fallback.
class ErrorBoundary extends React.Component { constructor(props) { super(props); this.state = { hasError: false }; } static getDerivedStateFromError(error) { return { hasError: true }; } componentDidCatch(error, errorInfo) { console.error('Error caught in ErrorBoundary:', error, errorInfo); } render() { if (this.state.hasError) { return <h1>Something went wrong.</h1>; } return this.props.children; } } const App = () => ( <ErrorBoundary> <MyComponent /> </ErrorBoundary> );
Render Props y Higher-Order Components (HOC)
- Render Props: Compartir lógica entre componentes utilizando una función como prop.
const RenderPropsComponent = ({ render }) => { const [state, setState] = useState('Initial State'); return render(state, setState); }; const App = () => ( <RenderPropsComponent render={(state, setState) => ( <div> <p>{state}</p> <button onClick={() => setState('New State')}>Change State</button> </div> )} /> );
- HOC: Reutilizar lógica envolviendo componentes.
const withExtraProps = (Component) => (props) => { const newProps = { extraProp: 'I am an extra prop' }; return <Component {...props} {...newProps} />; }; const MyComponent = ({ extraProp }) => <div>{extraProp}</div>; const EnhancedComponent = withExtraProps(MyComponent); // Uso <EnhancedComponent />;
Testing
- Jest y React Testing Library: Para pruebas unitarias y de integración.
import { render, screen, fireEvent } from '@testing-library/react'; import MyComponent from './MyComponent'; test('renders MyComponent and interacts with it', () => { render(<MyComponent />); const button = screen.getByText('Change Data'); fireEvent.click(button); expect(screen.getByText('New Data')).toBeInTheDocument(); });
Animaciones
- React Spring: Usa
react-spring
para crear animaciones fluidas y naturales.
import { useSpring, animated } from 'react-spring'; const AnimatedComponent = () => { const props = useSpring({ opacity: 1, from: { opacity: 0 } }); return <animated.div style={props}>I will fade in</animated.div>; };
- Framer Motion: Otra librería poderosa para animaciones en React.
import { motion } from 'framer-motion'; const MyComponent = () => ( <motion.div animate={{ x: 100 }} transition={{ duration: 1 }}> I will move to the right </motion.div> );
Integración con APIs
- Fetch: Realiza peticiones HTTP con
fetch
y maneja el estado de la respuesta.
const MyComponent = () => { const [data, setData] = useState(null); useEffect(() => { fetch('https://api.example.com/data') .then(response => response.json()) .then(data => setData(data)); }, []); if (!data) { return <div>Loading...</div>; } return <div>{data.name}</div>; };
- Axios: Usa
axios
para una sintaxis más limpia en peticiones HTTP.
import axios from 'axios'; const MyComponent = () => { const [data, setData] = useState(null); useEffect(() => { axios.get('https://api.example.com/data') .then(response => setData(response.data)); }, []); if (!data) { return <div>Loading...</div>; } return <div>{data.name}</div>; };
Context API
- Proveer y Consumir Contexto: Usa la Context API para manejar estado global en tu aplicación.
const MyContext = React.createContext(); const MyProvider = ({ children }) => { const [state, setState] = useState(initialState); return ( <MyContext.Provider value={{ state, setState }}> {children} </MyContext.Provider> ); }; const MyComponent = () => { const { state, setState } = useContext(MyContext); return <div>{state.someValue}</div>; };
¿Te ha resultado útil??
0 / 0