componenteDidMount equivalente en una función React / componente Hooks?

Respuestas:

199

Para la versión estable de hooks (React Version 16.8.0+)

por componentDidMount

useEffect(() => {
  // Your code here
}, []);

por componentDidUpdate

useEffect(() => {
  // Your code here
}, [yourDependency]);

por componentWillUnmount

useEffect(() => {
  // componentWillUnmount
  return () => {
     // Your code here
  }
}, [yourDependency]);

Entonces, en esta situación, debe pasar su dependencia a esta matriz. Supongamos que tienes un estado como este

const [count, setCount] = useState(0);

Y cada vez que el recuento aumenta, desea volver a renderizar su componente de función. Entonces tu useEffectdeberías lucir así

useEffect(() => {
  // <div>{count}</div>
}, [count]);

De esta manera, cada vez que su cuenta se actualice, su componente se volverá a procesar. Con suerte, esto ayudará un poco.

Mertcan Diken
fuente
¡Explicación completa! ¿Hay alguna forma de simular componentDidReceiveProps?
jeyko
1
No soy consciente de ello, incluso si existe. Puede consultar este hilo en github.com/facebook/react/issues/3279
Mertcan Diken
1
Gracias por esto ya que no estaba al tanto del segundo argumento en useState. Para cualquiera que lea esto, tenga en cuenta que dejar el segundo argumento undefinedhará que su efecto se active en cada renderizado (si no me equivoco).
dimiguel
¿Te refieres a dependencias de useEffect (pasando una matriz de dependencia)? Si es así, si lo deja vacío, es un error en el código. Para la deconstrucción de matrices, necesita tanto [count, setCount] porque count es su variable de estado en este ejemplo y setCount es su función para actualizar ese estado.
Mertcan Diken
Gracias por la respuesta. La documentación sobre esto está aquí reactjs.org/docs/hooks-effect.html
Josh
3

Aunque la respuesta aceptada funciona, no se recomienda. Cuando tiene más de un estado y lo usa con useEffect, le dará una advertencia sobre agregarlo a la matriz de dependencia o no usarlo en absoluto.

A veces causa el problema que puede generar un resultado impredecible. Así que le sugiero que se esfuerce un poco por reescribir su función como clase. Hay muy pocos cambios y puede tener algunos componentes como clase y otros como función. No está obligado a utilizar solo una convención.

Toma esto por ejemplo

function App() {
  const [appointments, setAppointments] = useState([]);
  const [aptId, setAptId] = useState(1);

  useEffect(() => {
    fetch('./data.json')
      .then(response => response.json())
      .then(result => {
        const apts = result.map(item => {
          item.aptId = aptId;
          console.log(aptId);
          setAptId(aptId + 1);
          return item;
        })
        setAppointments(apts);
      });
  }, []);

  return(...);
}

y

class App extends Component {
  constructor() {
    super();
    this.state = {
      appointments: [],
      aptId: 1,
    }
  }

  componentDidMount() {
    fetch('./data.json')
      .then(response => response.json())
      .then(result => {
        const apts = result.map(item => {
          item.aptId = this.state.aptId;
          this.setState({aptId: this.state.aptId + 1});
          console.log(this.state.aptId);
          return item;
        });
        this.setState({appointments: apts});
      });
  }

  render(...);
}

Esto es solo por ejemplo . así que no hablemos de las mejores prácticas o problemas potenciales con el código. Ambos tienen la misma lógica, pero el último solo funciona como se esperaba. Es posible que obtenga la funcionalidad componentDidMount con useEffect ejecutándose durante este tiempo, pero a medida que su aplicación crece, hay posibilidades de que PUEDA enfrentar algunos problemas. Entonces, en lugar de reescribir en esa fase, es mejor hacerlo en una etapa temprana.

Además, la POO no es tan mala, si la Programación Orientada a Procedimientos fuera suficiente, nunca hubiéramos tenido Programación Orientada a Objetos. A veces es doloroso, pero mejor (técnicamente, dejando de lado los problemas personales).

Aniket Kariya
fuente
1
Hice esto. Enfrenté problemas al usar ganchos. El problema desapareció después de convertirlo en clase.
Julez
2

No hay componentDidMountcomponentes funcionales, pero React Hooks proporciona una forma de emular el comportamiento usando el useEffecthook.

Pase una matriz vacía como segundo argumento useEffect()para ejecutar solo la devolución de llamada solo en el montaje.

Lea la documentación enuseEffect .

function ComponentDidMount() {
  const [count, setCount] = React.useState(0);
  React.useEffect(() => {
    console.log('componentDidMount');
  }, []);

  return (
    <div>
      <p>componentDidMount: {count} times</p>
      <button
        onClick={() => {
          setCount(count + 1);
        }}
      >
        Click Me
      </button>
    </div>
  );
}

ReactDOM.render(
  <div>
    <ComponentDidMount />
  </div>,
  document.querySelector("#app")
);
<script src="https://unpkg.com/[email protected]/umd/react.development.js"></script>
<script src="https://unpkg.com/[email protected]/umd/react-dom.development.js"></script>

<div id="app"></div>

Yangshun Tay
fuente
0

Quiere usar useEffect(), que, dependiendo de cómo use la función, puede actuar como componentDidMount ().

P.ej. podría usar una loadedpropiedad de estado personalizada que inicialmente se establece en falso, y cambiarla a verdadero al renderizar, y solo activar el efecto cuando este valor cambia.

Documentación

markmoxx
fuente
1
Esta solución no es la ideal. Es una mala idea usar un valor de estado solo para determinar si el componente se ha montado. Además, si tuviera que usar una propiedad, una referencia sería mejor ya que no desencadenaría otra renderización.
Yangshun Tay
0

el gancho equivalente exacto para componentDidMount () es

useEffect(()=>{},[]);

espero que esto sea útil :)

Aravinth
fuente