Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor fetchServerResponse #40674

Merged
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
6 changes: 2 additions & 4 deletions packages/next/client/app-index.tsx
Expand Up @@ -2,7 +2,8 @@
import '../build/polyfills/polyfill-module'
// @ts-ignore react-dom/client exists when using React 18
import ReactDOMClient from 'react-dom/client'
import React from 'react'
// TODO-APP: change to React.use once it becomes stable
import React, { experimental_use as use } from 'react'
import { createFromReadableStream } from 'next/dist/compiled/react-server-dom-webpack'

import measureWebVitals from './performance-relayer'
Expand All @@ -16,9 +17,6 @@ declare global {
const __webpack_require__: any
}

// TODO-APP: change to React.use once it becomes stable
const use = (React as any).experimental_use

// eslint-disable-next-line no-undef
const getChunkScriptFilename = __webpack_require__.u
const chunkFilenameMap: any = {}
Expand Down
11 changes: 6 additions & 5 deletions packages/next/client/components/app-router.client.tsx
Expand Up @@ -32,11 +32,11 @@ import { useReducerWithReduxDevtools } from './use-reducer-with-devtools'
/**
* Fetch the flight data for the provided url. Takes in the current router state to decide what to render server-side.
*/
export function fetchServerResponse(
export async function fetchServerResponse(
url: URL,
flightRouterState: FlightRouterState,
prefetch?: true
): Promise<FlightData> {
): Promise<[FlightData: FlightData]> {
const flightUrl = new URL(url)
const searchParams = flightUrl.searchParams
// Enable flight response
Expand All @@ -50,9 +50,10 @@ export function fetchServerResponse(
searchParams.append('__flight_prefetch__', '1')
}

const promise = fetch(flightUrl.toString())
const res = await fetch(flightUrl.toString())
// Handle the `fetch` readable stream that can be unwrapped by `React.use`.
return createFromFetch(promise)
const flightData: FlightData = await createFromFetch(Promise.resolve(res))
return [flightData]
}

/**
Expand Down Expand Up @@ -197,7 +198,7 @@ export default function AppRouter({
window.history.state?.tree || initialTree,
true
)
const flightData = await r
const [flightData] = await r
// @ts-ignore startTransition exists
React.startTransition(() => {
dispatch({
Expand Down
13 changes: 8 additions & 5 deletions packages/next/client/components/layout-router.client.tsx
@@ -1,6 +1,12 @@
'client'

import React, { useContext, useEffect, useRef } from 'react'
import React, {
useContext,
useEffect,
useRef,
// TODO-APP: change to React.use once it becomes stable
experimental_use as use,
} from 'react'
import type {
ChildProp,
//Segment
Expand All @@ -19,9 +25,6 @@ import {
import { fetchServerResponse } from './app-router.client'
// import { matchSegment } from './match-segments'

// TODO-APP: change to React.use once it becomes stable
const use = (React as any).experimental_use

/**
* Check if every segment in array a and b matches
*/
Expand Down Expand Up @@ -230,7 +233,7 @@ export function InnerLayoutRouter({
* Flight response data
*/
// When the data has not resolved yet `use` will suspend here.
const flightData = use(childNode.data)
const [flightData] = use(childNode.data)

// Handle case when navigating to page in `pages` from `app`
if (typeof flightData === 'string') {
Expand Down
10 changes: 4 additions & 6 deletions packages/next/client/components/reducer.ts
Expand Up @@ -6,13 +6,11 @@ import type {
FlightSegmentPath,
Segment,
} from '../../server/app-render'
import React from 'react'
// TODO-APP: change to React.use once it becomes stable
import { experimental_use as use } from 'react'
import { matchSegment } from './match-segments'
import { fetchServerResponse } from './app-router.client'

// TODO-APP: change to React.use once it becomes stable
const use = (React as any).experimental_use

/**
* Invalidate cache one level down from the router state.
*/
Expand Down Expand Up @@ -233,7 +231,7 @@ function fillCacheWithDataProperty(
newCache: CacheNode,
existingCache: CacheNode,
segments: string[],
fetchResponse: any
fetchResponse: () => ReturnType<typeof fetchServerResponse>
): { bailOptimistic: boolean } | undefined {
const isLastEntry = segments.length === 1

Expand Down Expand Up @@ -734,7 +732,7 @@ export function reducer(
cache,
state.cache,
segments.slice(1),
(): Promise<FlightData> => fetchServerResponse(url, optimisticTree)
() => fetchServerResponse(url, optimisticTree)
)

// If optimistic fetch couldn't happen it falls back to the non-optimistic case.
Expand Down
6 changes: 2 additions & 4 deletions packages/next/server/app-render.tsx
Expand Up @@ -2,7 +2,8 @@ import type { IncomingHttpHeaders, IncomingMessage, ServerResponse } from 'http'
import type { LoadComponentsReturnType } from './load-components'
import type { ServerRuntime } from '../types'

import React from 'react'
// TODO-APP: change to React.use once it becomes stable
import React, { experimental_use as use } from 'react'
import { ParsedUrlQuery, stringify as stringifyQuery } from 'querystring'
import { createFromReadableStream } from 'next/dist/compiled/react-server-dom-webpack'
import { renderToReadableStream } from 'next/dist/compiled/react-server-dom-webpack/writer.browser.server'
Expand All @@ -29,9 +30,6 @@ import { FlushEffectsContext } from '../shared/lib/flush-effects'
import { stripInternalQueries } from './internal-utils'
import type { ComponentsType } from '../build/webpack/loaders/next-app-loader'

// TODO-APP: change to React.use once it becomes stable
const use = (React as any).experimental_use

// this needs to be required lazily so that `next-server` can set
// the env before we require
const ReactDOMServer = shouldUseReactRoot
Expand Down
3 changes: 3 additions & 0 deletions packages/next/types/index.d.ts
Expand Up @@ -39,6 +39,9 @@ declare module 'react' {
interface LinkHTMLAttributes<T> extends HTMLAttributes<T> {
nonce?: string
}

// TODO-APP: check if this is the right type.
function experimental_use<T>(promise: Promise<T>): Awaited<T>
}

export type Redirect =
Expand Down