Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 8782f3b

Browse files
Add reactStrictMode as an option to render (#1390)
1 parent 65bc994 commit 8782f3b

File tree

4 files changed

+104
-9
lines changed

4 files changed

+104
-9
lines changed

‎src/__tests__/render.js

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -262,4 +262,38 @@ describe('render API', () => {
262262
`\`legacyRoot: true\` is not supported in this version of React. If your app runs React 19 or later, you should remove this flag. If your app runs React 18 or earlier, visit https://react.dev/blog/2022/03/08/react-18-upgrade-guide for upgrade instructions.`,
263263
)
264264
})
265+
266+
test('reactStrictMode in renderOptions has precedence over config when rendering', () => {
267+
const wrapperComponentMountEffect = jest.fn()
268+
function WrapperComponent({children}) {
269+
React.useEffect(() => {
270+
wrapperComponentMountEffect()
271+
})
272+
273+
return children
274+
}
275+
const ui = <div />
276+
configure({reactStrictMode: false})
277+
278+
render(ui, {wrapper: WrapperComponent, reactStrictMode: true})
279+
280+
expect(wrapperComponentMountEffect).toHaveBeenCalledTimes(2)
281+
})
282+
283+
test('reactStrictMode in config is used when renderOptions does not specify reactStrictMode', () => {
284+
const wrapperComponentMountEffect = jest.fn()
285+
function WrapperComponent({children}) {
286+
React.useEffect(() => {
287+
wrapperComponentMountEffect()
288+
})
289+
290+
return children
291+
}
292+
const ui = <div />
293+
configure({reactStrictMode: true})
294+
295+
render(ui, {wrapper: WrapperComponent})
296+
297+
expect(wrapperComponentMountEffect).toHaveBeenCalledTimes(2)
298+
})
265299
})

‎src/__tests__/renderHook.js

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import React from 'react'
2-
import {renderHook} from '../pure'
1+
import React,{useEffect} from 'react'
2+
import {configure,renderHook} from '../pure'
33

44
const isReact18 = React.version.startsWith('18.')
55
const isReact19 = React.version.startsWith('19.')
@@ -111,3 +111,31 @@ testGateReact19('legacyRoot throws', () => {
111111
`\`legacyRoot: true\` is not supported in this version of React. If your app runs React 19 or later, you should remove this flag. If your app runs React 18 or earlier, visit https://react.dev/blog/2022/03/08/react-18-upgrade-guide for upgrade instructions.`,
112112
)
113113
})
114+
115+
describe('reactStrictMode', () => {
116+
let originalConfig
117+
beforeEach(() => {
118+
// Grab the existing configuration so we can restore
119+
// it at the end of the test
120+
configure(existingConfig => {
121+
originalConfig = existingConfig
122+
// Don't change the existing config
123+
return {}
124+
})
125+
})
126+
127+
afterEach(() => {
128+
configure(originalConfig)
129+
})
130+
131+
test('reactStrictMode in renderOptions has precedence over config when rendering', () => {
132+
const hookMountEffect = jest.fn()
133+
configure({reactStrictMode: false})
134+
135+
renderHook(() => useEffect(() => hookMountEffect()), {
136+
reactStrictMode: true,
137+
})
138+
139+
expect(hookMountEffect).toHaveBeenCalledTimes(2)
140+
})
141+
})

‎src/pure.js

Lines changed: 35 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -77,8 +77,8 @@ const mountedContainers = new Set()
7777
*/
7878
const mountedRootEntries = []
7979

80-
function strictModeIfNeeded(innerElement) {
81-
return getConfig().reactStrictMode
80+
function strictModeIfNeeded(innerElement,reactStrictMode) {
81+
return reactStrictMode??getConfig().reactStrictMode
8282
? React.createElement(React.StrictMode, null, innerElement)
8383
: innerElement
8484
}
@@ -91,14 +91,24 @@ function wrapUiIfNeeded(innerElement, wrapperComponent) {
9191

9292
function createConcurrentRoot(
9393
container,
94-
{hydrate, onCaughtError, onRecoverableError, ui, wrapper: WrapperComponent},
94+
{
95+
hydrate,
96+
onCaughtError,
97+
onRecoverableError,
98+
ui,
99+
wrapper: WrapperComponent,
100+
reactStrictMode,
101+
},
95102
) {
96103
let root
97104
if (hydrate) {
98105
act(() => {
99106
root = ReactDOMClient.hydrateRoot(
100107
container,
101-
strictModeIfNeeded(wrapUiIfNeeded(ui, WrapperComponent)),
108+
strictModeIfNeeded(
109+
wrapUiIfNeeded(ui, WrapperComponent),
110+
reactStrictMode,
111+
),
102112
{onCaughtError, onRecoverableError},
103113
)
104114
})
@@ -144,17 +154,31 @@ function createLegacyRoot(container) {
144154

145155
function renderRoot(
146156
ui,
147-
{baseElement, container, hydrate, queries, root, wrapper: WrapperComponent},
157+
{
158+
baseElement,
159+
container,
160+
hydrate,
161+
queries,
162+
root,
163+
wrapper: WrapperComponent,
164+
reactStrictMode,
165+
},
148166
) {
149167
act(() => {
150168
if (hydrate) {
151169
root.hydrate(
152-
strictModeIfNeeded(wrapUiIfNeeded(ui, WrapperComponent)),
170+
strictModeIfNeeded(
171+
wrapUiIfNeeded(ui, WrapperComponent),
172+
reactStrictMode,
173+
),
153174
container,
154175
)
155176
} else {
156177
root.render(
157-
strictModeIfNeeded(wrapUiIfNeeded(ui, WrapperComponent)),
178+
strictModeIfNeeded(
179+
wrapUiIfNeeded(ui, WrapperComponent),
180+
reactStrictMode,
181+
),
158182
container,
159183
)
160184
}
@@ -180,6 +204,7 @@ function renderRoot(
180204
baseElement,
181205
root,
182206
wrapper: WrapperComponent,
207+
reactStrictMode,
183208
})
184209
// Intentionally do not return anything to avoid unnecessarily complicating the API.
185210
// folks can use all the same utilities we return in the first place that are bound to the container
@@ -212,6 +237,7 @@ function render(
212237
queries,
213238
hydrate = false,
214239
wrapper,
240+
reactStrictMode,
215241
} = {},
216242
) {
217243
if (onUncaughtError !== undefined) {
@@ -248,6 +274,7 @@ function render(
248274
onRecoverableError,
249275
ui,
250276
wrapper,
277+
reactStrictMode,
251278
})
252279

253280
mountedRootEntries.push({container, root})
@@ -273,6 +300,7 @@ function render(
273300
hydrate,
274301
wrapper,
275302
root,
303+
reactStrictMode,
276304
})
277305
}
278306

‎types/index.d.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,11 @@ export interface RenderOptions<
156156
* @see https://testing-library.com/docs/react-testing-library/api/#wrapper
157157
*/
158158
wrapper?: React.JSXElementConstructor<{children: React.ReactNode}> | undefined
159+
/**
160+
* When enabled, <StrictMode> is rendered around the inner element.
161+
* If defined, overrides the value of `reactStrictMode` set in `configure`.
162+
*/
163+
reactStrictMode?: boolean
159164
}
160165

161166
type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /