Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to execute store.unsubscribe from useEffect using React hooks and Redux

I have a React stateless component using redux and hooks. I need to display the number of items on page load (useEffect) and update it every time I add or remove an item (store.subscribe)

useEffect(() => {
    setState({
        items: store.getState().items.length
    });
}, []);

store.subscribe(() => {
    setState({
        items: store.getState().items.length
    });
});

but this is causing the console to display the 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. .

How can I unsubscribe from inside useEffect?

like image 423
user3174311 Avatar asked Nov 25 '19 15:11

user3174311


People also ask

How do I unsubscribe from useEffect?

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. The instruction is pretty clear and straightforward, "cancel all subscriptions and asynchronous tasks in a useEffect cleanup function".

How does useEffect () hook gets executed?

useEffect() hook runs the side-effect after initial rendering, and on later renderings only if the name value changes.

How do you subscribe and unsubscribe in React JS?

useEffect(()=>{ const sub = interval(10). subscribe(); function unsub(){ sub. unsubscribe(); } return unsub; });

How do you stop useEffect from running twice?

Simply remove the <React. StrictMode> tags around the <App> tag, and this should disable strict mode for your app! You can also only include this tag in pages where you do want strict mode enabled, to opt-in on a page by page basis.


2 Answers

If you set the second parameter of useEffect call to [], the effect callback function would act as ComponentDidMount. If that callback function returns a function, this function will be called just before the component is unmounted(ComponentWillUnmount).

And I guess this setState should be replaced with setItems as below. Please try this code.

const [items, setItems] = useState([]);
useEffect(() => {
    setItems(store.getState().items.length);
    
    
    const unsubscribe = store.subscribe(() => {
        setItems(store.getState().items.length);
    });
    
    return unsubscribe;
}, []);
like image 106
TopW3 Avatar answered Oct 06 '22 00:10

TopW3


Return a function from useEffect to do cleanup. So the returned function will be called when the component gets unmounted.

store.subscribe return an unsubscribe function. Save its reference using useRef hook and return the same reference from the useEffect hook.

Read about it in the docs: https://reactjs.org/docs/hooks-effect.html#effects-with-cleanup.

const storeRef = useRef(() => {});
useEffect(() => {
  storeRef.current = store.subscribe(() => {
    setState({
      items: store.getState().items.length
    });
  });

  return storeRef.current;
}, []);

useEffect(() => {
  setState({
    items: store.getState().items.length
  });

  return storeRef.current;
}, []);
like image 22
Murli Prajapati Avatar answered Oct 05 '22 22:10

Murli Prajapati