Skip to content

Commit

Permalink
remove flush effects errors
Browse files Browse the repository at this point in the history
  • Loading branch information
huozhi committed May 14, 2022
1 parent 1375b20 commit b59504c
Show file tree
Hide file tree
Showing 10 changed files with 28 additions and 267 deletions.
24 changes: 0 additions & 24 deletions errors/client-flush-effects.md

This file was deleted.

8 changes: 0 additions & 8 deletions errors/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -638,14 +638,6 @@
"title": "opening-an-issue",
"path": "/errors/opening-an-issue.md"
},
{
"title": "multiple-flush-effects",
"path": "/errors/multiple-flush-effects.md"
},
{
"title": "client-flush-effects",
"path": "/errors/client-flush-effects.md"
},
{
"title": "import-next",
"path": "/errors/import-next.md"
Expand Down
9 changes: 0 additions & 9 deletions errors/multiple-flush-effects.md

This file was deleted.

92 changes: 26 additions & 66 deletions packages/next/server/render.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,6 @@ import {
continueFromInitialStream,
} from './node-web-streams-helper'
import { ImageConfigContext } from '../shared/lib/image-config-context'
import { FlushEffectsContext } from '../shared/lib/flush-effects'
import { interopDefault } from '../lib/interop-default'
import stripAnsi from 'next/dist/compiled/strip-ansi'
import { urlQueryToSearchParams } from '../shared/lib/router/utils/querystring'
Expand Down Expand Up @@ -794,62 +793,33 @@ export async function renderToHTML(
return <>{styles}</>
}

let flushEffects: Array<() => React.ReactNode> | null = null
function FlushEffectContainer({ children }: { children: JSX.Element }) {
// If the client tree suspends, this component will be rendered multiple
// times before we flush. To ensure we don't call old callbacks corresponding
// to a previous render, we clear any registered callbacks whenever we render.
flushEffects = null

const flushEffectsImpl = React.useCallback(
(callbacks: Array<() => React.ReactNode>) => {
if (flushEffects) {
throw new Error(
'The `useFlushEffects` hook cannot be used more than once.' +
'\nRead more: https://nextjs.org/docs/messages/multiple-flush-effects'
)
}
flushEffects = callbacks
},
[]
)

return (
<FlushEffectsContext.Provider value={flushEffectsImpl}>
{children}
</FlushEffectsContext.Provider>
)
}

const AppContainer = ({ children }: { children: JSX.Element }) => (
<FlushEffectContainer>
<RouterContext.Provider value={router}>
<AmpStateContext.Provider value={ampState}>
<HeadManagerContext.Provider
value={{
updateHead: (state) => {
head = state
},
updateScripts: (scripts) => {
scriptLoader = scripts
},
scripts: initialScripts,
mountedInstances: new Set(),
}}
<RouterContext.Provider value={router}>
<AmpStateContext.Provider value={ampState}>
<HeadManagerContext.Provider
value={{
updateHead: (state) => {
head = state
},
updateScripts: (scripts) => {
scriptLoader = scripts
},
scripts: initialScripts,
mountedInstances: new Set(),
}}
>
<LoadableContext.Provider
value={(moduleName) => reactLoadableModules.push(moduleName)}
>
<LoadableContext.Provider
value={(moduleName) => reactLoadableModules.push(moduleName)}
>
<StyleRegistry registry={jsxStyleRegistry}>
<ImageConfigContext.Provider value={images}>
{children}
</ImageConfigContext.Provider>
</StyleRegistry>
</LoadableContext.Provider>
</HeadManagerContext.Provider>
</AmpStateContext.Provider>
</RouterContext.Provider>
</FlushEffectContainer>
<StyleRegistry registry={jsxStyleRegistry}>
<ImageConfigContext.Provider value={images}>
{children}
</ImageConfigContext.Provider>
</StyleRegistry>
</LoadableContext.Provider>
</HeadManagerContext.Provider>
</AmpStateContext.Provider>
</RouterContext.Provider>
)

// The `useId` API uses the path indexes to generate an ID for each node.
Expand Down Expand Up @@ -1480,17 +1450,7 @@ export async function renderToHTML(
// this must be called inside bodyResult so appWrappers is
// up to date when `wrapApp` is called
const flushEffectHandler = (): string => {
const allFlushEffects = [
styledJsxFlushEffect,
...(flushEffects || []),
]
const flushed = ReactDOMServer.renderToString(
<>
{allFlushEffects.map((flushEffect, i) => (
<React.Fragment key={i}>{flushEffect()}</React.Fragment>
))}
</>
)
const flushed = ReactDOMServer.renderToString(styledJsxFlushEffect())
return flushed
}

Expand Down
41 changes: 2 additions & 39 deletions packages/next/server/view-render.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ import {
createBufferedTransformStream,
continueFromInitialStream,
} from './node-web-streams-helper'
import { FlushEffectsContext } from '../shared/lib/flush-effects'
import { isDynamicRoute } from '../shared/lib/router/utils'
import { tryGetPreviewData } from './api-utils/node'

Expand Down Expand Up @@ -389,37 +388,8 @@ export async function renderToHTML(
return <>{styles}</>
}

let flushEffects: Array<() => React.ReactNode> | null = null
function FlushEffectContainer({ children }: { children: JSX.Element }) {
// If the client tree suspends, this component will be rendered multiple
// times before we flush. To ensure we don't call old callbacks corresponding
// to a previous render, we clear any registered callbacks whenever we render.
flushEffects = null

const flushEffectsImpl = React.useCallback(
(callbacks: Array<() => React.ReactNode>) => {
if (flushEffects) {
throw new Error(
'The `useFlushEffects` hook cannot be used more than once.' +
'\nRead more: https://nextjs.org/docs/messages/multiple-flush-effects'
)
}
flushEffects = callbacks
},
[]
)

return (
<FlushEffectsContext.Provider value={flushEffectsImpl}>
{children}
</FlushEffectsContext.Provider>
)
}

const AppContainer = ({ children }: { children: JSX.Element }) => (
<FlushEffectContainer>
<StyleRegistry registry={jsxStyleRegistry}>{children}</StyleRegistry>
</FlushEffectContainer>
<StyleRegistry registry={jsxStyleRegistry}>{children}</StyleRegistry>
)

const renderServerComponentData = isFlight
Expand Down Expand Up @@ -462,14 +432,7 @@ export async function renderToHTML(
})

const flushEffectHandler = (): string => {
const allFlushEffects = [styledJsxFlushEffect, ...(flushEffects || [])]
const flushed = ReactDOMServer.renderToString(
<>
{allFlushEffects.map((flushEffect, i) => (
<React.Fragment key={i}>{flushEffect()}</React.Fragment>
))}
</>
)
const flushed = ReactDOMServer.renderToString(styledJsxFlushEffect())
return flushed
}

Expand Down
21 changes: 0 additions & 21 deletions packages/next/shared/lib/flush-effects.ts

This file was deleted.

36 changes: 0 additions & 36 deletions test/integration/react-18/app/pages/use-flush-effect/client.js

This file was deleted.

12 changes: 0 additions & 12 deletions test/integration/react-18/app/pages/use-flush-effect/custom.js

This file was deleted.

This file was deleted.

29 changes: 0 additions & 29 deletions test/integration/react-18/test/concurrent.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,22 +16,6 @@ export default (context, _render) => {
}
}

it('throws if useFlushEffects is used more than once', async () => {
await renderViaHTTP(context.appPort, '/use-flush-effect/multiple-calls')
expect(context.stderr).toContain(
'Error: The `useFlushEffects` hook cannot be used more than once.'
)
})

it('throws if useFlushEffects is called on the client', async () => {
await withBrowser('/use-flush-effect/client', async (browser) => {
await check(
() => browser.waitForElementByCss('#error').text(),
/useFlushEffects can not be called on the client/
)
})
})

it('flushes styled-jsx styles as the page renders', async () => {
const html = await renderViaHTTP(
context.appPort,
Expand All @@ -51,17 +35,4 @@ export default (context, _render) => {
)
})
})

it('flushes custom effects', async () => {
await withBrowser('/use-flush-effect/custom', async (browser) => {
await check(
() => browser.waitForElementByCss('#custom-flush-effect-1').text(),
/foo/
)
await check(
() => browser.waitForElementByCss('#custom-flush-effect-2').text(),
/bar/
)
})
})
}

0 comments on commit b59504c

Please sign in to comment.