diff --git a/srcs/hooks/core/hooksDispatcher.js b/srcs/hooks/core/hooksDispatcher.js index fb3b754..f8a7572 100644 --- a/srcs/hooks/core/hooksDispatcher.js +++ b/srcs/hooks/core/hooksDispatcher.js @@ -5,6 +5,7 @@ import { mountReducer, updateReducer } from "../useReducer/useReducerImpl"; import { mountEffect, updateEffect } from "../useEffect/useEffectImpl"; +import { mountCallback, updateCallback } from "../useCallback/useCallbackImpl"; import { mountRef, updateRef } from "../useRef/useRefImpl"; /** @@ -19,6 +20,7 @@ export const hookDispatcherOnMount = { useReducer: mountReducer, useEffect: mountEffect, // useMemo: mountMemo, + useCallback: mountCallback, useRef: mountRef, }; @@ -34,5 +36,6 @@ export const hookDispatcherOnUpdate = { useReducer: updateReducer, useEffect: updateEffect, // useMemo: updateMemo, + useCallback: updateCallback, useRef: updateRef, }; diff --git a/srcs/hooks/index.js b/srcs/hooks/index.js index 5016c55..f056346 100644 --- a/srcs/hooks/index.js +++ b/srcs/hooks/index.js @@ -1,5 +1,6 @@ import useReducer from "./useReducer/useReducer.js"; import useEffect from "./useEffect/useEffect.js"; +import useCallback from "./useCallback/useCallback.js"; import useRef from "./useRef/useRef.js"; -export { useReducer, useEffect, useRef }; +export { useReducer, useEffect, useCallback, useRef }; diff --git a/srcs/hooks/useCallback/useCallback.js b/srcs/hooks/useCallback/useCallback.js index e6336d5..a30172d 100644 --- a/srcs/hooks/useCallback/useCallback.js +++ b/srcs/hooks/useCallback/useCallback.js @@ -3,7 +3,7 @@ * @description This module defines the useCallback function. */ -import c from "../core/core"; +import hookCore from "../core/hookCore"; /** * @description This function is useCallback hook. @@ -11,6 +11,8 @@ import c from "../core/core"; * @argument {Array} deps * @returns {Function} */ -export const useCallback = (callback, deps) => { - return c.RfsCurrentDispatcher.current.useMemo(() => callback, deps); +const useCallback = (callback, deps) => { + return hookCore.RfsCurrentDispatcher.current.useCallback(callback, deps); }; + +export default useCallback; diff --git a/srcs/hooks/useCallback/useCallbackImpl.js b/srcs/hooks/useCallback/useCallbackImpl.js new file mode 100644 index 0000000..bb89eda --- /dev/null +++ b/srcs/hooks/useCallback/useCallbackImpl.js @@ -0,0 +1,48 @@ +import { + mountWorkInProgressHook, + updateWorkInProgressHook, +} from "../core/workInProgressHook"; + +import { areHookDepsEqual } from "../useEffect/useEffectImpl"; + +/** + * + * @param {Function} callback + * @param {Array} deps + * @description - useMemo와 동일한 코드입니다. + * 하나 다른 점은 callback을 실행하지 않고 callback그 자체를 저장한다는 것입니다. + * @returns + */ +export const mountCallback = (callback, deps) => { + const hook = mountWorkInProgressHook(); + const nextDeps = deps === undefined ? null : deps; + hook.memoizedState = [callback, nextDeps]; + return callback; +}; + +/** + * + * @param {Function} callback + * @param {Array} deps + * @description - 만약 deps가 같다면, 이전에 저장된 callback을 반환합니다. + * 만약 deps가 다르다면, 새로운 callback을 저장하고 반환합니다. + * 이때 callback은 deps에 의존하기 때문에 deps가 변경되었을 때, + * 해당 deps를 반영한 새로운 callback을 반환합니다. + * @returns + */ +export const updateCallback = (callback, deps) => { + const hook = updateWorkInProgressHook(); + const nextDeps = deps === undefined ? null : deps; + const prevState = hook.memoizedState; + + if (nextDeps !== null) { + const prevDeps = prevState[1]; + if (prevDeps !== null) { + if (areHookDepsEqual(nextDeps, prevDeps)) { + return prevState[0]; + } + } + } + hook.memoizedState = [callback, nextDeps]; + return callback; +}; diff --git a/srcs/hooks/useEffect/useEffectImpl.js b/srcs/hooks/useEffect/useEffectImpl.js index 3732e6c..18548a1 100644 --- a/srcs/hooks/useEffect/useEffectImpl.js +++ b/srcs/hooks/useEffect/useEffectImpl.js @@ -51,7 +51,7 @@ const createFunctionComponentUpdateQueue = () => { * useEffect의 deps 배열을 비교하여 같다면 true, 다르다면 false를 반환합니다. * @returns */ -const areHookDepsEqual = (prevDeps, nextDeps) => { +export const areHookDepsEqual = (prevDeps, nextDeps) => { for (let i = 0; i < prevDeps.length && i < nextDeps.length; i++) { if (is(prevDeps[i], nextDeps[i])) { continue;