diff --git a/README.md b/README.md index 3ecb7af..f59e842 100644 --- a/README.md +++ b/README.md @@ -2,12 +2,14 @@ Familiar with the `Can't perform a React state update on an unmounted component` error? this tiny package is to help solve that as well prevent stalled state updates in react components. -Execution of asynchronous requests in React useEffect hook has some quite interesting gotchas. First is the possibility of running state updates even when the component had been unmounted. +Execution of asynchronous/scheduled calls such as setTimeout and setIntervals in React useEffect hook has some quite interesting gotchas. First is the possibility of running state updates even when the component had been unmounted. Second is the possibility of running state updates from an effect that has already stalled, because you failed to clean the effect properly. Third is unoptimization of network requests. Why make network requests when the effect is stalled? +Finally, these things can result to memory leaks, infinite loop/lifetime execution of code in client applications. + These three problems can be seen in the codebase below ```tsx @@ -43,9 +45,9 @@ Finally, could we abort a network request when the effect is no longer valid? fo npm install @teclone/react-use-effect-cleaner ``` -## Sample Usage +## Sample Usage with Api Request Cleanup -Below is how to utilize this module to solve the problems of the code show earlier. +Below is how to utilize this module to solve the problems of the code shown earlier. ```tsx import { useState, useEffect } from 'react'; @@ -86,6 +88,52 @@ The module utilizes the Proxy web api to create a middleware for all state modif AbortController is supported by popular request client libraries including Fetch and Axios. +## Sample Usage with SetTimeout/SetInterval Cleanup + +Below is an example of how to use the createEffectCleaner to clean up setTimeouts or setInterval. + +```tsx +import { useState, useEffect } from 'react'; +import { createEffectCleaner } from '@teclone/react-use-effect-cleaner'; + +// sample asynchronous request +const getUserProfile = (userId, abortSignal) => Promise.resolve({ id: userId }); + +const Profile = ({ userId }) => { + const [count, setCount] = useState(0); + + useEffect(() => { + const timoutIds = { count: 0 }; + const intervalIds = { count: 0 }; + + // create effects + const effects = createEffectCleaner( + { + setCount, + }, + { timeoutIds, intervalIds } + ); + + timeoutIds.count = setTimeout(() => { + effects.setCount((count) => count + 1); + }, 10000); + + intervalIds.count = setInterval(() => { + effects.setCount((count) => count + 1); + }, 1000); + + // return the cleaner + return effects.clean(); + }, [userId]); + + return ( +
Current Count: {count}
+