我需要什么:在我的组件中,当 useContext 的值发生变化时,我需要显示一个加载微调器。我找到了一个解决方案,但我不太喜欢它。
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} }
</>
)
}
如果我这样做,那么每次安装组件时都会调用 useEffect,即使 stateDB 不会改变。所以我的问题是:有没有办法只在 useContext 的值发生变化时才调用这个 useEffect ?由于 useContext 挂钩每次都返回新对象,因此 useEffect 认为它与前一个不同。
在 useDB 里面我有:
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>
}
我发现的解决方案:
// 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} }
</>
)
}