Как запомнить значение пользовательского хука useContext в React?

Что мне нужно: в моем компоненте мне нужно показать счетчик загрузки при изменении значения из 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 не будет изменен. Итак, мой вопрос: есть ли способ вызвать этот useEffect только тогда, когда значение из useContext изменится? Так как хук 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} }
   </>
)
}


person Nichita    schedule 15.11.2020    source источник
comment
вы должны запомнить это внутри useDB   -  person Dupocas    schedule 15.11.2020
comment
Решение, которое я обнаружил, заключается в добавлении новой переменной вне компонента и установке для нее значения true, а в useEffect проверьте, является ли эта переменная флага истинной, затем покажите useTimeout и покажите загрузку и установите флаг в значение false таким образом, когда компонент будет быть установлен снова, useEffect проверит, является ли флаг истинным, но он будет ложным, и загрузочный компонент больше не будет отображаться   -  person Nichita    schedule 15.11.2020
comment
Дюпокас, как мне запомнить состояние внутри моего контекста?   -  person Nichita    schedule 15.11.2020
comment
Поделитесь кодом для useDB   -  person Dupocas    schedule 15.11.2020
comment
@Dupocas, пожалуйста, взгляните сейчас!   -  person Nichita    schedule 15.11.2020
comment
Это кажется лишь косвенно связанным с useContext, когда на самом деле вы спрашиваете, как предотвратить запуск useEffect при первоначальном рендеринге, который вы уже обнаружили для себя. Хотя лучше использовать useRef, чтобы все было удобно для React - см. on-the-initial-render">эта тема. В качестве альтернативы, почему бы просто не инициализировать state каким-нибудь нейтральным значением, например null, с которым можно свериться при первом рендеринге?   -  person lawrence-witt    schedule 15.11.2020