Unleash / unleash-client-nextjs

Unleash SDK for Next.js
28 stars 9 forks source link

Unleash: unable to fetch feature toggles TypeError: this.fetch is not a function #52

Closed Daniel-Boll closed 1 year ago

Daniel-Boll commented 1 year ago

Describe the bug

Problem

I'm integrating Unleash v5.3.0-main in a NextJS 13 project via docker-compose. The objective is to evaluate feature flags both on the server and client sides. However, I'm observing inconsistent results between the two.

Server Side Implementation:

For server side flag evaluation, I'm using the flag function from @unleash/nextjs inside app/page.tsx. Here's a simplified snippet:

export default async function Home() {
  // Session ID retrieval and fallback
  const sessionId = cookies().get(COOKIE_NAME)?.value || `${Math.floor(Math.random() * 1_000_000_000)}`;
  const { enabled, variant, error } = await flag("nextjs-example", { sessionId }, { fetchOptions: { next: { revalidate: 1 } } });
  // ... other logic
}

Client Side Implementation:

On the client side, I'm using the FlagProvider and useFlag from @unleash/nextjs/client inside app/layout.tsx and another component respectively:

export default function RootLayout({ children }: { children: React.ReactNode }) {
  // Session ID retrieval and fallback
  const sessionId = cookies().get(COOKIE_NAME)?.value || `${Math.floor(Math.random() * 1_000_000_000)}`;
  // ... Provider setup
}
export const ClientSideCard = ({ title, description, img, price, index }: ClientSideCardProps) => {
  const enabled = useFlag("nextjs-example");
  // ... other logic
}

Issues Observed:

  1. Inconsistent Flags: Toggling the feature flag doesn't reflect the changes accurately on the server side. There seems to be a discrepancy in the state of the flag between the server and client sides.
  2. Client Side Error: The client side throws the following error:
app-index.js:31 Unleash: unable to fetch feature toggles TypeError: this.fetch is not a function
    ... stack trace from unleash-proxy-client@2.5.0

Steps to reproduce the bug

  1. Setup Environment:
    • Initialize a new NextJS 13 project.
    • Run Unleash v5.3.0-main using docker-compose.
  2. Server Side Integration:
    • In app/page.tsx, import the necessary modules from next/headers and @unleash/nextjs.
    • Add the logic to retrieve or generate a sessionId.
    • Fetch the feature flag named "nextjs-example" using the flag function and log the results.
  3. Client Side Integration:
    • In app/layout.tsx:
      • Import the required modules from @unleash/nextjs/client.
      • Retrieve or generate the same sessionId as in the server side.
      • Wrap the component's children with the FlagProvider component, setting up the configuration as provided in your example.
    • In a separate component (like ClientSideCard), use the useFlag hook to fetch the state of the "nextjs-example" flag.
  4. Run the Application:
    • Start the NextJS application and access the home page or the relevant page where the above code resides.
  5. Toggle the Feature Flag:
    • Using the Unleash dashboard or interface, toggle the state of the "nextjs-example" flag.
  6. Observe Results:
    • On the server side, observe the console log for the flag's state. Note if the change in flag state is not reflecting correctly.
    • On the client side, inspect the browser console for the mentioned error related to the unleash-proxy-client@2.5.0.

Expected behavior

Upon integrating Unleash with NextJS 13, both server and client sides should consistently and accurately reflect the current state of the "nextjs-example" feature flag without any errors. Any toggling of the flag in the Unleash dashboard should be immediately and synchronously reflected in both evaluations. No client-side errors related to fetching feature flags should occur.

Logs, error output, etc.

Unleash: unable to fetch feature toggles TypeError: this.fetch is not a function
    at UnleashClient.eval (webpack-internal:///(:3001/app-pages-browser)/./node_modules/.pnpm/unleash-proxy-client@2.5.0/node_modules/unleash-proxy-client/build/index.js:399:51)
    at step (webpack-internal:///(:3001/app-pages-browser)/./node_modules/.pnpm/unleash-proxy-client@2.5.0/node_modules/unleash-proxy-client/build/index.js:59:23)
    at Object.eval [as next] (webpack-internal:///(:3001/app-pages-browser)/./node_modules/.pnpm/unleash-proxy-client@2.5.0/node_modules/unleash-proxy-client/build/index.js:40:53)
    at eval (webpack-internal:///(:3001/app-pages-browser)/./node_modules/.pnpm/unleash-proxy-client@2.5.0/node_modules/unleash-proxy-client/build/index.js:34:71)
    at new Promise (<anonymous>)
    at __awaiter (webpack-internal:///(:3001/app-pages-browser)/./node_modules/.pnpm/unleash-proxy-client@2.5.0/node_modules/unleash-proxy-client/build/index.js:30:12)
    at UnleashClient.fetchToggles (webpack-internal:///(:3001/app-pages-browser)/./node_modules/.pnpm/unleash-proxy-client@2.5.0/node_modules/unleash-proxy-client/build/index.js:382:16)
    at UnleashClient.eval (webpack-internal:///(:3001/app-pages-browser)/./node_modules/.pnpm/unleash-proxy-client@2.5.0/node_modules/unleash-proxy-client/build/index.js:310:51)
    at step (webpack-internal:///(:3001/app-pages-browser)/./node_modules/.pnpm/unleash-proxy-client@2.5.0/node_modules/unleash-proxy-client/build/index.js:59:23)
    at Object.eval [as next] (webpack-internal:///(:3001/app-pages-browser)/./node_modules/.pnpm/unleash-proxy-client@2.5.0/node_modules/unleash-proxy-client/build/index.js:40:53)
    at fulfilled (webpack-internal:///(:3001/app-pages-browser)/./node_modules/.pnpm/unleash-proxy-client@2.5.0/node_modules/unleash-proxy-client/build/index.js:31:58)

Screenshots

No response

Additional context

Additional Context:

Understanding if there are known issues, changes in configuration methods, or any updates in the recent v5.3.0-main version of Unleash that could lead to such behaviors would be beneficial.

Unleash version

"@unleash/nextjs": "^1.2.0"

Subscription type

Open source

Hosting type

Self-hosted

SDK information (language and version)

"unleash-proxy-client": "^2.5.0"
Tymek commented 1 year ago

I'll try to reproduce it. @Daniel-Boll what's your Node version? (node -v).

Also, if you have useFlag did you try to mark ClientSideCard component with "use client"?

Daniel-Boll commented 1 year ago

@Tymek my node version is v16.19.0. And yes, ClientSideCard is marked as "use client"

Tymek commented 1 year ago

I could not reproduce this. My attempt is available here: https://github.com/Tymek/unleash-nextjs-drafts/tree/d8eeb1340dd7da40fe7cafe6ecbe4d611b487d29

Tested on Node v16.20.2, SDK v1.2.0, Next v13.4.17. If you're sure that there is an error in some previous version please let me know. You can also check with explicitly generated API keys.

On my end everything worked out-of-the-box, and I verified that it was on Node v16. Issues like this one should never take place and I'm willing to investigate further.

Daniel-Boll commented 1 year ago

Thank you, @Tymek, for the prompt response. I will take a look at your suggestion and attempt to try it from scratch once again. If I succeed, I'll be sure to inform you. I'm hopeful that the previous issue was merely a mistake on my part. Thanks once again.