13
votes

I have a functional component where I get a value from my localStorage and use that value to set a value in a state:

localforage.getItem<string>('sortType').then((value) => {
  setSortType(value)
})

const [sortType, setSortType] = useState('release_date');

When I run the component I get a log:

Warning: Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in a useEffect cleanup function.

I've read that this happens because I'm using a async method localforage.getItem on a state. But I haven't found a solution that would work in a functional component.

2
Could it be a case of defining the states before you set the state? - bishal

2 Answers

11
votes

You are setting the state after the promise resolves, which can cause this code to run after the component has unmounted.

To resolve this, you can check if the component is still mounted before setting the state:

const isMountedRef = useRef(true)
useEffect(() => () => { isMountedRef.current = false }, [])

Since the dependency array is empty the effect is called when the component mounts, and the callback is executed when it dismounts

// somewhere in your code later
localforage.getItem<string>('sortType').then((value) => {
  if (isMountedRef.current) {
      setSortType(value)
  }
})
1
votes

Try to run the sortType from localStorage once by using React.useEffect as below:

const [sortType, setSortType] = useState('release_date');

React.useEffect(() => {
  localforage.getItem<string>('sortType').then((value) => {
    setSortType(value)
  })
}, []);