[1] makeVar 생성
reactive variable 생성
import { makeVar, useReactiveVar } from '@apollo/client'; const initialFullCartridgeDataState = null; type FullCartridgeDataStateType = number[] | null; export const fullCartridgeDataStateVar = makeVar<FullCartridgeDataStateType>( initialFullCartridgeDataState, ); export const useGetFullCartridgeDataState = (): FullCartridgeDataStateType => { const statefulFullCartridgeDataState = useReactiveVar( fullCartridgeDataStateVar, ); return statefulFullCartridgeDataState; }; export const setFullCartridgeDataState = ( newFullCartridgeDataState: | FullCartridgeDataStateType | ((value: FullCartridgeDataStateType) => FullCartridgeDataStateType), ): void => { if (newFullCartridgeDataState instanceof Function) { fullCartridgeDataStateVar( newFullCartridgeDataState(fullCartridgeDataStateVar()), ); return; } fullCartridgeDataStateVar(newFullCartridgeDataState); };
[2] reactive variable에 값 설정하는 훅 생성
promise가 필요한데, 값이 없는 경우에는 가져와서 설정한 후에 반환할 수 있도록 해야함.
그럴려면 디펜던시에 reactive variable을 넣고, 없을 경우에는 데이터를 가져와서 reactive variable을 set하는 로직을 타도록 하면, reactive variable 값이 변경됐으므로 다시 호출되면서, 값이 있는 경우의 로직을 타서 값을 계산하고 반환한다.
import { useCallback, useMemo } from 'react'; import { setFullCartridgeDataState, useGetFullCartridgeDataState, } from 'states/fullCartridgeDataState'; import { CartridgeNameInformation } from 'utils'; import { getCartridgeNameInformationFromRawData } from 'utils/functions/getCartridgeNameInformationFromRawData'; import { logWebHook } from 'utils/functions/logWebHook'; import { useGetHardwareController } from './useGetHardwareController'; export const useGetCartridgeNameInformation = ( onError?: () => void, ): CartridgeNameInformation[] | null => { const fullCartridgeData = useGetFullCartridgeDataState(); const hardwareController = useGetHardwareController(); const getAndSetFullCartridgeData = useCallback(async (): Promise<void> => { try { const result = await hardwareController.getFullCartridgeData(); logWebHook('getFullCartridgeData 결과 : ', result); setFullCartridgeDataState(result); } catch { onError?.(); } }, [hardwareController, onError]); const cartridgeNameInformation = useMemo< CartridgeNameInformation[] | null >(() => { if (fullCartridgeData === null) { getAndSetFullCartridgeData(); return null; } const newNameInformation = getCartridgeNameInformationFromRawData(fullCartridgeData); return newNameInformation; }, [fullCartridgeData, getAndSetFullCartridgeData]); return cartridgeNameInformation; };
[3] react component에서 훅을 호출해서 로직에 가져다 쓰면 됨
컴포넌트에서는 그냥 커스텀 훅을 호출해서 값을 가져오는 것으로 생각하고 하면 된다.
import { useMemo } from 'react'; import { useGetNutrientNameState } from 'states/nutrientNameState'; import { CartridgeInformation } from 'utils'; import { getCartridgeInformationFromRawData } from 'utils/functions/getCartridgeInformationFromRawData'; import { useGetCartridgeNameInformation } from './useGetCartridgeNameInformation'; import { useGetCartridgePercentageInformation } from './useGetCartridgePercentageInformation'; export const useGetCartridgeInformation = (): CartridgeInformation[] => { const tempNameData = useGetCartridgeNameInformation(); const tempPercentageData = useGetCartridgePercentageInformation(); const { firmwareNames, readableNames } = useGetNutrientNameState(); const information = useMemo<CartridgeInformation[]>(() => { if ( tempNameData === null || tempPercentageData === null || firmwareNames.length === 0 || readableNames.length === 0 ) { return []; } const newCartridgeInformation = getCartridgeInformationFromRawData( tempNameData, tempPercentageData, firmwareNames, readableNames, ); return newCartridgeInformation; }, [firmwareNames, readableNames, tempNameData, tempPercentageData]); return information; };