diff --git a/src/server/__tests__/ssr.test.ts b/src/server/__tests__/ssr.test.ts new file mode 100644 index 00000000..3acb246d --- /dev/null +++ b/src/server/__tests__/ssr.test.ts @@ -0,0 +1,20 @@ +/** + * @jest-environment node + */ +import { useState } from 'react' +import { renderHook, act } from '..' + +// This verifies that renderHook can be called in +// a SSR-like environment. +describe('renderHook', () => { + function useLoading() { + if (typeof window !== 'undefined') { + const [loading, setLoading] = useState(false) + return { loading, setLoading } + } + } + + test('should not throw in SSR environment', () => { + expect(() => renderHook(() => useLoading())).not.toThrowError('document is not defined') + }) +}) diff --git a/src/server/pure.ts b/src/server/pure.ts index 1bacd008..01aa1ac5 100644 --- a/src/server/pure.ts +++ b/src/server/pure.ts @@ -2,7 +2,7 @@ import ReactDOMServer from 'react-dom/server' import ReactDOM from 'react-dom' import { act } from 'react-dom/test-utils' -import { RendererProps, RendererOptions } from '../types/react' +import { RendererOptions, RendererProps } from '../types/react' import { createRenderHook } from '../core' import { createTestHarness } from '../helpers/createTestHarness' @@ -12,8 +12,8 @@ function createServerRenderer( { wrapper }: RendererOptions ) { let renderProps: TProps | undefined - let hydrated = false - const container = document.createElement('div') + let container: HTMLDivElement | undefined + let serverOutput = '' const testHarness = createTestHarness(rendererProps, wrapper, false) return { @@ -21,35 +21,37 @@ function createServerRenderer( renderProps = props act(() => { try { - const serverOutput = ReactDOMServer.renderToString(testHarness(props)) - container.innerHTML = serverOutput + serverOutput = ReactDOMServer.renderToString(testHarness(props)) } catch (e: unknown) { rendererProps.setError(e as Error) } }) }, hydrate() { - if (hydrated) { + if (container) { throw new Error('The component can only be hydrated once') } else { + container = document.createElement('div') + container.innerHTML = serverOutput act(() => { - ReactDOM.hydrate(testHarness(renderProps), container) + ReactDOM.hydrate(testHarness(renderProps), container || null) }) - hydrated = true } }, rerender(props?: TProps) { - if (!hydrated) { + if (!container) { throw new Error('You must hydrate the component before you can rerender') } act(() => { - ReactDOM.render(testHarness(props), container) + ReactDOM.render(testHarness(props), container || null) }) }, unmount() { - if (hydrated) { + if (container) { act(() => { - ReactDOM.unmountComponentAtNode(container) + if (typeof container !== 'undefined') { + ReactDOM.unmountComponentAtNode(container) + } }) } },