Recomendaciones y buenas prácticas

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 y componentWillUnmount.
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 y Yup 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

Deja una respuesta 0

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.