What I need: In my component I need to show a loading spinner when a value from useContext changes. I found a solution but I do not really like it.
const MyComponent = () => {
const { stateDB } = useDB // custom useContext hook
// stateDB is an array of objects
const [loading, setLoading] = useState(false)
useEffect(() => {
// I need to show loading each time the stateDB changes
// but not each time the component will mount
setLoading(true)
setTimeout(() => {
setLoading(false)
}, 2000)
}, [stateDB])
return(
<>
{ loading ? <LoadingComponent/> : {stateDB.someValue} }
</>
)
}
If I do it like that then the useEffect is gonna be called each time when the component will be mounted even if the stateDB will not be changed. So my question is: is there a way how call this useEffect only then when the value from the useContext will change ? As the useContext hook each time returns new object so useEffect considers it as different from the previous one.
Inside useDB I have:
const DBContext = React.createContext();
export const useDB = () => {
return useContext(DBContext);
}
export const DBProvider = ({children}) => {
// the state i need in my component
const [ state, setState ] = useState([]) // default empty array
const fetchSomeData = async () => {
const response = await db...// fetchin data here
.then( () => setState(fetchedData) )
return () => response()
}
useEffect( () => {
fetchSomeData() // fetch the data only once
}, [])
value = { state } // the state I need in my component
return <DBContext.Provider value={value}>
{children}
</DBContext.Provider>
}
the solution I found out:
// in my component
let flag = true;
const MyComponent = () => {
const { stateDB } = useDB
const [loading, setLoading] = useState(false)
useEffect( () => {
if (flag) {
flag = false;
setLoading(true)
setTimeout(() => {
setLoading(false)
}, 1200)
}
}, [flag])
return(
<>
{ loading ? <LoadingComponent/> : {stateDB.someValue} }
</>
)
}