mirror of
https://github.com/zoriya/react-native-web.git
synced 2026-06-02 18:41:17 +00:00
[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
This commit is contained in:
@@ -32,8 +32,9 @@ npm install --save react react-dom react-native-web
|
|||||||
|
|
||||||
## Example
|
## Example
|
||||||
|
|
||||||
React Native for Web exports its components and a reference to the `React`
|
React Native for Web exports its components, a reference to the `react`
|
||||||
installation. Styles are defined with, and used as JavaScript objects.
|
installation, and the `react-dom` methods (customized for Web). Styles are defined
|
||||||
|
with, and used as JavaScript objects.
|
||||||
|
|
||||||
Component:
|
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
|
```js
|
||||||
// server.js
|
// server.js
|
||||||
import App from './components/App'
|
import App from './components/App'
|
||||||
import React, { StyleSheet } from 'react-native-web'
|
import React from 'react-native-web'
|
||||||
|
|
||||||
const html = React.renderToString(<App />);
|
const html = React.renderToString(<App />);
|
||||||
const css = StyleSheet.renderToString();
|
|
||||||
|
|
||||||
const Html = () => (
|
const Html = () => (
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<meta charSet="utf-8" />
|
<meta charSet="utf-8" />
|
||||||
<meta content="initial-scale=1,width=device-width" name="viewport" />
|
<meta content="initial-scale=1,width=device-width" name="viewport" />
|
||||||
<style id="react-stylesheet" dangerouslySetInnerHTML={{ __html: css } />
|
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="react-root" dangerouslySetInnerHTML={{ __html: html }} />
|
<div id="react-root" dangerouslySetInnerHTML={{ __html: html }} />
|
||||||
@@ -111,19 +110,14 @@ const Html = () => (
|
|||||||
)
|
)
|
||||||
```
|
```
|
||||||
|
|
||||||
Render styles on the client:
|
Rendering on the client automatically includes your app styles:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
// client.js
|
// client.js
|
||||||
import App from './components/App'
|
import App from './components/App'
|
||||||
import React, { StyleSheet } from 'react-native-web'
|
import React from 'react-native-web'
|
||||||
import ReactDOM from 'react-dom'
|
|
||||||
|
|
||||||
const reactRoot = document.getElementById('react-root')
|
React.render(<App />, document.getElementById('react-root'))
|
||||||
const reactStyleSheet = document.getElementById('react-stylesheet')
|
|
||||||
|
|
||||||
ReactDOM.render(<App />, reactRoot)
|
|
||||||
reactStyleSheet.textContent = StyleSheet.renderToString()
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## APIs
|
## APIs
|
||||||
|
|||||||
@@ -7,7 +7,8 @@ module.exports = {
|
|||||||
},
|
},
|
||||||
externals: [{
|
externals: [{
|
||||||
'react': true,
|
'react': true,
|
||||||
'react-dom': true
|
'react-dom': true,
|
||||||
|
'react-dom/server': true
|
||||||
}],
|
}],
|
||||||
output: {
|
output: {
|
||||||
filename: 'react-native-web.js',
|
filename: 'react-native-web.js',
|
||||||
|
|||||||
@@ -2,7 +2,5 @@
|
|||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<title>React Native for Web</title>
|
<title>React Native for Web</title>
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<meta name="description" content="The core React Native components adapted and expanded upon for the web">
|
|
||||||
<style id="react-stylesheet"></style>
|
|
||||||
<div id="react-root"></div>
|
<div id="react-root"></div>
|
||||||
<script src="/examples.js"></script>
|
<script src="/examples.js"></script>
|
||||||
|
|||||||
+2
-5
@@ -2,8 +2,7 @@ import { MediaProvider, matchMedia } from 'react-media-queries'
|
|||||||
import App from './components/App'
|
import App from './components/App'
|
||||||
import createGetter from 'react-media-queries/lib/createMediaQueryGetter'
|
import createGetter from 'react-media-queries/lib/createMediaQueryGetter'
|
||||||
import createListener from 'react-media-queries/lib/createMediaQueryListener'
|
import createListener from 'react-media-queries/lib/createMediaQueryListener'
|
||||||
import React, { StyleSheet } from '../src'
|
import React from '../src'
|
||||||
import ReactDOM from 'react-dom'
|
|
||||||
|
|
||||||
const mediaQueries = {
|
const mediaQueries = {
|
||||||
small: '(min-width: 300px)',
|
small: '(min-width: 300px)',
|
||||||
@@ -12,11 +11,9 @@ const mediaQueries = {
|
|||||||
}
|
}
|
||||||
const ResponsiveApp = matchMedia()(App)
|
const ResponsiveApp = matchMedia()(App)
|
||||||
|
|
||||||
ReactDOM.render(
|
React.render(
|
||||||
<MediaProvider getMedia={createGetter(mediaQueries)} listener={createListener(mediaQueries)}>
|
<MediaProvider getMedia={createGetter(mediaQueries)} listener={createListener(mediaQueries)}>
|
||||||
<ResponsiveApp />
|
<ResponsiveApp />
|
||||||
</MediaProvider>,
|
</MediaProvider>,
|
||||||
document.getElementById('react-root')
|
document.getElementById('react-root')
|
||||||
)
|
)
|
||||||
|
|
||||||
document.getElementById('react-stylesheet').textContent = StyleSheet.renderToString()
|
|
||||||
|
|||||||
@@ -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 />, div)
|
||||||
|
assert.ok(document.getElementById('react-stylesheet'))
|
||||||
|
})
|
||||||
|
|
||||||
|
test('"renderToString" creates style sheet', () => {
|
||||||
|
const result = React.renderToString(<div />)
|
||||||
|
assert.ok(result.indexOf('react-stylesheet') > -1)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('"renderToStaticMarkup" creates style sheet', () => {
|
||||||
|
const result = React.renderToStaticMarkup(<div />)
|
||||||
|
assert.ok(result.indexOf('react-stylesheet') > -1)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
+37
-4
@@ -1,5 +1,8 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
|
import ReactDOM from 'react-dom'
|
||||||
|
import ReactDOMServer from 'react-dom/server'
|
||||||
|
|
||||||
|
// api
|
||||||
import StyleSheet from './modules/StyleSheet'
|
import StyleSheet from './modules/StyleSheet'
|
||||||
|
|
||||||
// components
|
// components
|
||||||
@@ -11,7 +14,35 @@ import TextInput from './components/TextInput'
|
|||||||
import Touchable from './components/Touchable'
|
import Touchable from './components/Touchable'
|
||||||
import View from './components/View'
|
import View from './components/View'
|
||||||
|
|
||||||
|
const renderStyle = () => {
|
||||||
|
return `<style id='react-stylesheet'>${StyleSheet.renderToString()}</style>`
|
||||||
|
}
|
||||||
|
|
||||||
|
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 = {
|
const ReactNative = {
|
||||||
|
// apis
|
||||||
|
StyleSheet,
|
||||||
|
|
||||||
// components
|
// components
|
||||||
Image,
|
Image,
|
||||||
ListView,
|
ListView,
|
||||||
@@ -21,11 +52,13 @@ const ReactNative = {
|
|||||||
Touchable,
|
Touchable,
|
||||||
View,
|
View,
|
||||||
|
|
||||||
// apis
|
|
||||||
StyleSheet,
|
|
||||||
|
|
||||||
// React
|
// React
|
||||||
...React
|
...React,
|
||||||
|
...ReactDOM,
|
||||||
|
...ReactDOMServer,
|
||||||
|
render,
|
||||||
|
renderToString,
|
||||||
|
renderToStaticMarkup
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = ReactNative
|
module.exports = ReactNative
|
||||||
|
|||||||
Reference in New Issue
Block a user