UNPKG

1.7 kBTypeScriptView Raw
1import { CurrentRenderContext } from '@react-navigation/core';
2import * as React from 'react';
3
4import ServerContext, { ServerContextType } from './ServerContext';
5import type { ServerContainerRef } from './types';
6
7type Props = ServerContextType & {
8 children: React.ReactNode;
9};
10
11/**
12 * Container component for server rendering.
13 *
14 * @param props.location Location object to base the initial URL for SSR.
15 * @param props.children Child elements to render the content.
16 * @param props.ref Ref object which contains helper methods.
17 */
18export default React.forwardRef(function ServerContainer(
19 { children, location }: Props,
20 ref: React.Ref<ServerContainerRef>
21) {
22 React.useEffect(() => {
23 console.error(
24 "'ServerContainer' should only be used on the server with 'react-dom/server' for SSR."
25 );
26 }, []);
27
28 const current: { options?: object } = {};
29
30 if (ref) {
31 const value = {
32 getCurrentOptions() {
33 return current.options;
34 },
35 };
36
37 // We write to the `ref` during render instead of `React.useImperativeHandle`
38 // This is because `useImperativeHandle` will update the ref after 'commit',
39 // and there's no 'commit' phase during SSR.
40 // Mutating ref during render is unsafe in concurrent mode, but we don't care about it for SSR.
41 if (typeof ref === 'function') {
42 ref(value);
43 } else {
44 // @ts-expect-error: the TS types are incorrect and say that ref.current is readonly
45 ref.current = value;
46 }
47 }
48
49 return (
50 <ServerContext.Provider value={{ location }}>
51 <CurrentRenderContext.Provider value={current}>
52 {children}
53 </CurrentRenderContext.Provider>
54 </ServerContext.Provider>
55 );
56});