From cc10de43ebc7ac9a4cdf1e1ac1f27374619c7e51 Mon Sep 17 00:00:00 2001 From: Nicolas Gallagher Date: Tue, 22 Dec 2015 00:21:30 +0000 Subject: [PATCH] [change] export or replace react-dom methods This change adds the react-dom methods to the main export, since this is a Web-only environment (React Native does something similar). It augments the default render methods in order to move style sheet management under the control of the library (necessary for code-splitting support). Relates to #52 --- README.md | 22 ++++++--------- config/webpack.config.js | 3 ++- examples/index.html | 2 -- examples/index.js | 7 ++--- src/__tests__/index-test.js | 54 +++++++++++++++++++++++++++++++++++++ src/index.js | 41 +++++++++++++++++++++++++--- 6 files changed, 103 insertions(+), 26 deletions(-) create mode 100644 src/__tests__/index-test.js diff --git a/README.md b/README.md index 4d4f7ab7..0c28568b 100644 --- a/README.md +++ b/README.md @@ -32,8 +32,9 @@ npm install --save react react-dom react-native-web ## Example -React Native for Web exports its components and a reference to the `React` -installation. Styles are defined with, and used as JavaScript objects. +React Native for Web exports its components, a reference to the `react` +installation, and the `react-dom` methods (customized for Web). Styles are defined +with, and used as JavaScript objects. Component: @@ -87,22 +88,20 @@ const styles = StyleSheet.create({ }) ``` -Pre-render styles on the server: +Pre-rendering on the server automatically includes your app styles: ```js // server.js import App from './components/App' -import React, { StyleSheet } from 'react-native-web' +import React from 'react-native-web' const html = React.renderToString(); -const css = StyleSheet.renderToString(); const Html = () => ( -
diff --git a/examples/index.js b/examples/index.js index 12f2d8e3..e155d0c5 100644 --- a/examples/index.js +++ b/examples/index.js @@ -2,8 +2,7 @@ import { MediaProvider, matchMedia } from 'react-media-queries' import App from './components/App' import createGetter from 'react-media-queries/lib/createMediaQueryGetter' import createListener from 'react-media-queries/lib/createMediaQueryListener' -import React, { StyleSheet } from '../src' -import ReactDOM from 'react-dom' +import React from '../src' const mediaQueries = { small: '(min-width: 300px)', @@ -12,11 +11,9 @@ const mediaQueries = { } const ResponsiveApp = matchMedia()(App) -ReactDOM.render( +React.render( , document.getElementById('react-root') ) - -document.getElementById('react-stylesheet').textContent = StyleSheet.renderToString() diff --git a/src/__tests__/index-test.js b/src/__tests__/index-test.js new file mode 100644 index 00000000..a047a866 --- /dev/null +++ b/src/__tests__/index-test.js @@ -0,0 +1,54 @@ +/* eslint-env mocha */ + +import * as utils from '../modules/specHelpers' +import assert from 'assert' +import React from '..' + +suite('ReactNativeWeb', () => { + suite('exports', () => { + test('React', () => { + assert.ok(React) + }) + + test('ReactDOM methods', () => { + assert.ok(React.findDOMNode) + assert.ok(React.render) + assert.ok(React.unmountComponentAtNode) + }) + + test('ReactDOM/server methods', () => { + assert.ok(React.renderToString) + assert.ok(React.renderToStaticMarkup) + }) + }) + + suite('render methods', () => { + const id = 'test' + let div + + setup(() => { + div = document.createElement('div') + div.id = id + document.body.appendChild(div) + }) + + teardown(() => { + document.body.removeChild(div) + }) + + test('"render" creates style sheet', () => { + React.render(
, div) + assert.ok(document.getElementById('react-stylesheet')) + }) + + test('"renderToString" creates style sheet', () => { + const result = React.renderToString(
) + assert.ok(result.indexOf('react-stylesheet') > -1) + }) + + test('"renderToStaticMarkup" creates style sheet', () => { + const result = React.renderToStaticMarkup(
) + assert.ok(result.indexOf('react-stylesheet') > -1) + }) + }) +}) diff --git a/src/index.js b/src/index.js index 8bdf5891..95e8ad70 100644 --- a/src/index.js +++ b/src/index.js @@ -1,5 +1,8 @@ import React from 'react' +import ReactDOM from 'react-dom' +import ReactDOMServer from 'react-dom/server' +// api import StyleSheet from './modules/StyleSheet' // components @@ -11,7 +14,35 @@ import TextInput from './components/TextInput' import Touchable from './components/Touchable' import View from './components/View' +const renderStyle = () => { + return `` +} + +const render = (element, container, callback) => { + const styleElement = document.getElementById('react-stylesheet') + if (!styleElement) { + const style = renderStyle() + container.insertAdjacentHTML('beforebegin', style) + } + return ReactDOM.render(element, container, callback) +} + +const renderToString = (element) => { + const style = renderStyle() + const html = ReactDOMServer.renderToString(element) + return `${style}\n${html}` +} + +const renderToStaticMarkup = (element) => { + const style = renderStyle() + const html = ReactDOMServer.renderToStaticMarkup(element) + return `${style}\n${html}` +} + const ReactNative = { + // apis + StyleSheet, + // components Image, ListView, @@ -21,11 +52,13 @@ const ReactNative = { Touchable, View, - // apis - StyleSheet, - // React - ...React + ...React, + ...ReactDOM, + ...ReactDOMServer, + render, + renderToString, + renderToStaticMarkup } module.exports = ReactNative