From f8f696b57a1e0134db76f00b582931ca342e7869 Mon Sep 17 00:00:00 2001 From: Muneeb Date: Wed, 22 Apr 2026 15:52:37 +0200 Subject: [PATCH] fix(nextjs): remove unnecessary csrfToken dependency from useCallback Remove csrfToken from the secureFetch useCallback dependency array and drop the redundant newToken !== csrfToken comparison. React's setState already bails out for identical primitive values, so the equality check was unnecessary. The unstable function reference was causing the CsrfContextValue to change on every token update, triggering unwanted re-renders in downstream components. Fixes #53 --- .changeset/fix-usecallback-csrftoken-dep.md | 11 +++++++++++ packages/nextjs/src/client/react.tsx | 4 ++-- 2 files changed, 13 insertions(+), 2 deletions(-) create mode 100644 .changeset/fix-usecallback-csrftoken-dep.md diff --git a/.changeset/fix-usecallback-csrftoken-dep.md b/.changeset/fix-usecallback-csrftoken-dep.md new file mode 100644 index 0000000..3e6a3f8 --- /dev/null +++ b/.changeset/fix-usecallback-csrftoken-dep.md @@ -0,0 +1,11 @@ +--- +"@csrf-armor/nextjs": patch +--- + +fix(react): remove unnecessary `csrfToken` dependency from `useCallback` + +`secureFetch` previously listed `csrfToken` in its `useCallback` dependency array, causing the function reference to change every time the token updated. This made the `CsrfContextValue` unstable and triggered unnecessary re-renders in any component consuming `useCsrf()`. + +The token equality check (`newToken !== csrfToken`) was also redundant because React's `setState` already bails out for identical primitive values. Removing both the dependency and the comparison fixes the re-render issue without changing behavior. + +Fixes #53 diff --git a/packages/nextjs/src/client/react.tsx b/packages/nextjs/src/client/react.tsx index 405f0f9..da05a8c 100644 --- a/packages/nextjs/src/client/react.tsx +++ b/packages/nextjs/src/client/react.tsx @@ -169,13 +169,13 @@ export function CsrfProvider({ const headerName = config?.headerName ?? 'x-csrf-token'; const newToken = response.headers.get(headerName); - if (newToken && newToken !== csrfToken) { + if (newToken) { setCsrfToken(newToken); } return response; }, - [config, csrfToken] + [config] ); const value = useMemo(