Custom Hooks

Por 9.99€ al mes tendrás acceso completo a todos los cursos. Sin matrícula ni permanencia.

En todos los casos siguientes, la función calculateArea está definida dentro del propio Hook. Suele ser lo común, aunque también se podría calcular el resultado final directamente en el componente App.

Exportando cada hook por separado

App.js

import useRectangle from './use-rectangle';

function App() {
  const { height, width, setWidth, setHeight, area } = useRectangle(0, 0);
  return (
    <div className="App">
      <input type="text" placeholder="ancho" onChange={e => setWidth(e.target.value)} />
      <input type="text" placeholder="alto" onChange={e => setHeight(e.target.value)} />
      <output>
        {area}
      </output>
    </div>
  );
}

export default App;

use-rectangle.js

import { useState } from "react";

const useRectangle = (initialHeight, initialWidth) => {
    const [width, setWidth] = useState(initialWidth);
    const [height, setHeight] = useState(initialHeight);

    const calculateArea = () => width * height;

    const area = calculateArea();

    return { width, height, setWidth, setHeight, area };
}

export default useRectangle;

Exportando todos los hooks en un solo objeto

App.js

import useRectangle from './use-rectangle';

function App() {
  const [state, area, { updateState }] = useRectangle(0, 0);
  return (
    <div className="App">
      <input type="text" placeholder="ancho" onChange={e => updateState('width', e.target.value)} />
      <input type="text" placeholder="alto" onChange={e => updateState('height', e.target.value)} />
      <output>
        {area}
      </output>
    </div>
  );
}

export default App;

use-rectangle.js

import { useState } from 'react';

const useRectangle = () => {
    const [state, setState] = useState({ width: 0, height: 0, area: 0 });

    const updateState = (prop, val) => {
        const obj = { ...state, [prop]: val };
        obj.area = obj.width * obj.height;
        setState(obj);
    }

    return { state, updateState }
}

export default useRectangle

Usando useReducer

App.js

import useRectangle from './use-rectangle';

function App() {

  const {state, updateState } = useRectangle();
  return (
    <div className="App">
      <input type="text" placeholder="ancho" onChange={e => updateState('width', e.target.value)} />
      <input type="text" placeholder="alto" onChange={e => updateState('height', e.target.value)} />
      <output>
        {state.area}
      </output>
    </div>
  );
}

export default App;

use-rectangle.js

import { useReducer } from "react";

const calculatateArea = (opt) => {
    const area = opt.width * opt.height;
    return area;
};

// Patrón State Reducer
// El reducer es un método que modifica el estado a través de acciones
// el return del reducer será el nuevo estado 

const reducer = (state, { prop, type, value }) => {
    if (type === "update") {
        const newState = {
            ...state,
            [prop]: value,
        };
        return { ...newState, price: calculatateArea(newState) }
    }
}

const useRectangle = () => {
    // useReducer es un método que devuelve el estado y el dispatch, que es un método que utilizaremos para modificar el estado

    const [state, dispatch] = useReducer(reducer, {
        width: 0,
        height: 0,
    });

    // El dispatch ejecutará automáticamente el reducer, pasándole el estado actual y los parámetros para modifcarlo

    const updateState = (prop, value) => dispatch({
        type: 'update',
        prop,
        value,
    });

    const area = calculatateArea(state);

    return [state, { updateState }, area];
}

export default useRectangle;

Context API + useReducer vs Redux

Podríamos usar Context API y useReducer para obtener algo similar a lo que podemos hacer con Redux. Sin embargo, con Context API, todos los componentes serán renderizados de nuevo, mientras que con Redux sólo serán renderizados los componentes que lo necesiten, por tanto para proyectos que muestren muchos componentes Redux es más apropiado.

Por 9.99€ al mes tendrás acceso completo a todos los cursos. Sin matrícula ni permanencia.