1

我需要什么:在我的组件中,当 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} }
   </>
)
}

4

0 回答 0