Skip to content
This repository was archived by the owner on Apr 13, 2023. It is now read-only.
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Override renderFunction for getDataFromTree when using React Native.
React Native is obviously not Node.js, but it also doesn't identify itself
as a browser-like environment, so importing `react-dom/server` fails due
to the transitive dependency on Node's built-in `stream` module:
#2592 (comment)

To fix this problem, we need to avoid automatically importing
`react-dom/server` in React Native (especially since `getDataFromTree` is
unlikely to be used in RN apps). Since module dependencies are effectively
static, detecting React Native at runtime is not an option, so we need
help from the React Native bundler. Specifically, if we import the render
function from `react-dom/server` in a small wrapper module, we should be
able to override that module in React Native.

According to the documentation of "Platform-specific extensions," it
appears we can make this work using the `.native.js` file extension.
Specifically, React Native is supposed to prefer `lib/*.native.js` modules
to their `lib/*.js` counterparts:
https://facebook.github.io/react-native/docs/platform-specific-code#platform-specific-extensions

The `src/defaultRenderFunction.native.ts` module exports a default
function that throws an exception, which makes `getDataFromTree` fail with
a helpful error message in React Native. Calling `getMarkupFromTree` with
a custom `renderFunction` may be a little more work for React Native apps,
but that seems acceptable because server-side rendering is not a common
use case in React Native, compared to client/server web applications.
  • Loading branch information
benjamn committed Nov 17, 2018
commit 7a0c19256a7cb039b155190016272e8c4eeb28b7
3 changes: 3 additions & 0 deletions src/defaultRenderFunction.native.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export default function(_: React.ReactNode): string {
throw new Error("Please use getMarkupFromTree with a custom renderFunction in React Native");
}
3 changes: 3 additions & 0 deletions src/defaultRenderFunction.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export {
renderToStaticMarkup as default
} from "react-dom/server";
8 changes: 4 additions & 4 deletions src/getDataFromTree.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as React from 'react';
import * as PropTypes from 'prop-types';
import { renderToStaticMarkup } from 'react-dom/server';
import defaultRenderFunction from './defaultRenderFunction';
import Query from './Query';

// Like a Set, but for tuples. In practice, this class is used to store
Expand Down Expand Up @@ -93,14 +93,14 @@ export default function getDataFromTree(
context,
// If you need to configure this renderFunction, call getMarkupFromTree
// directly instead of getDataFromTree.
renderFunction: renderToStaticMarkup,
renderFunction: defaultRenderFunction,
});
}

export type GetMarkupFromTreeOptions = {
tree: React.ReactNode;
context?: { [key: string]: any };
renderFunction?: typeof renderToStaticMarkup;
renderFunction?: typeof defaultRenderFunction;
};

export function getMarkupFromTree({
Expand All @@ -109,7 +109,7 @@ export function getMarkupFromTree({
// The rendering function is configurable! We use renderToStaticMarkup as
// the default, because it's a little less expensive than renderToString,
// and legacy usage of getDataFromTree ignores the return value anyway.
renderFunction = renderToStaticMarkup,
renderFunction = defaultRenderFunction,
}: GetMarkupFromTreeOptions): Promise<string> {
const renderPromises = new RenderPromises();

Expand Down