Estoy recibiendo el siguiente error:

No se puede realizar una actualización de estado de React en un componente desmontado. Esta es una operación no operativa, pero indica una pérdida de memoria en su aplicación. Para solucionarlo, cancele todas las suscripciones y tareas asincrónicas en una función de limpieza useEffect.

Esto se debe al siguiente componente basado en ganchos

import { animated, config, useTransition } from 'react-spring'
import styled from 'styled-components'
import React, { useState, useEffect } from 'react'

const ProductImage = styled(animated.div)`
  background: ${({ colour }) => colour} url(${({ image }) => image}) no-repeat center;
  background-size: cover;
  transition: background-image 0.2s ease-in-out;
  width: 100%;
  height: 100%;
`

interface Props {
  images: string[]
  colour?: string
}

const Gallery = ({ images, colour }: Props) => {
  const [index, set] = useState(0)
  const transitions = useTransition(images[index], image => image, {
    from: { opacity: 0 },
    enter: { opacity: 1 },
    leave: { opacity: 0 },
    config: config.molasses
  })
  useEffect(() => void setInterval(() => set(state => (state + 1) % images.length), 5000), [])
  return (
    <>
      {transitions.map(({ item, props, key }) => (
        <ProductImage key={key} image={item} style={props} colour={colour} />
      ))}
    </>
  )
}

export default Gallery

Creo que se llama al método set() después de salir de la página. Normalmente manejaría esto dentro de un método componentDidUnmount(), donde podría establecer alguna bandera para detener la llamada. No estoy seguro de qué hacer cuando utilizo ganchos. Alguien sabe cómo resolver esto?

0
userqwert 9 oct. 2019 a las 21:05

1 respuesta

La mejor respuesta

El problema es este efecto:

useEffect(() => void setInterval(() => set(state => (state + 1) % images.length), 5000), [])

Esto inicia un intervalo que nunca termina. Debes decirle a useEffect cómo limpiar tu efecto devolviendo una función de limpieza:

useEffect(() => {
  const id = setInterval(() => set(state => (state + 1) % images.length, 5000)

  // return cleanup method
  return () => clearInterval(id);
}, []);
7
Brandon 9 oct. 2019 a las 18:19