I missed something with useEffect, useCallback and deps.
I have one context and one component. My component load every data I need with fetch() and set a boolean to true in the context to show a spinner. I use the context in another component when I need it.
const LoadingApp = ({children}) => {
const loadingContext = useContext(LoadingContext);
const fetchMyData = useCallback(() => {
loadingContext.setLoading(true);
}, [loadingContext]);
useEffect(() => {
fetchMyData();
}, [fetchMyData]);
return (
<React.Fragment>
{children}
</React.Fragment>
);
};
const LoadingProvider = ({children}) => {
const [loading, setLoading] = useState(false);
const setLoading = useCallback((isLoading) => {
setLoading(loading + (isLoading ? 1: -1));
}, [setLoading, loading]);
const isLoading = useCallback(() => {
return loading > 0;
}, [loading]);
return (
<LoadingContext.Provider value={{setLoading, isLoading}}>
{children}
</LoadingContext.Provider>
)
}
I know I could remove the deps from useEffect or useCallback but it seems to be the wrong way to fix my issue as deps is required.
How could I call a function in a context in a useEffect or useCallback without re-rendering everything?
If you are calling setLoading
, then you are always going to trigger a rerender which is what you want.
You could have an empty deps
, which means the effect will only run once.
The context always changes when the loading
value changes. Change the dependencies of useEffect
to only depend on setLoading
, which is based on useCallback
( useState
setter doesn't change as well), and will stay fixed.
const { setLoading } = useContext(LoadingContext);
const fetchMyData = useCallback(() => {
setLoading(true);
}, [setLoading]);
You don't actually need the useCallback
, since it does the same thing that the original setLoading
is doing. You can safely remove this:
const setLoading = useCallback((isLoading) => {
setLoading(isLoading);
}, [loading]);
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.