mirror of
https://github.com/zoriya/react-native-web.git
synced 2026-05-24 23:25:40 +00:00
Update README; add guides to docs
This commit is contained in:
@@ -9,12 +9,13 @@ The most common and best supported accessibility features of the Web are
|
||||
exposed as the props: `accessible`, `accessibilityLabel`,
|
||||
`accessibilityLiveRegion`, and `accessibilityRole`.
|
||||
|
||||
React Native for Web does not provide a way to directly control the rendered
|
||||
HTML element. The `accessibilityRole` prop is used to infer an [analogous HTML
|
||||
element][html-aria-url] to use in addition, where possible. While this may
|
||||
contradict some ARIA recommendations, it also helps avoid certain HTML5
|
||||
conformance errors and accessibility anti-patterns (e.g., giving a `heading`
|
||||
role to a `button` element).
|
||||
React Native for Web does not provide a way to directly control the type of the
|
||||
rendered HTML element. The `accessibilityRole` prop is used to infer an
|
||||
[analogous HTML element][html-aria-url] to use in addition to the resulting
|
||||
ARIA `role`, where possible. While this may contradict some ARIA
|
||||
recommendations, it also helps avoid certain HTML5 conformance errors and
|
||||
accessibility anti-patterns (e.g., giving a `heading` role to a `button`
|
||||
element).
|
||||
|
||||
For example:
|
||||
|
||||
@@ -24,7 +25,8 @@ For example:
|
||||
* `<Text accessibilityRole='link' href='/' />` => `<a role='link' href='/' />`.
|
||||
* `<View accessibilityRole='main' />` => `<main role='main' />`.
|
||||
|
||||
See the component documentation for more details.
|
||||
Other ARIA properties should be set via [direct
|
||||
manipulation](./direct-manipulation.md).
|
||||
|
||||
[aria-in-html-url]: https://w3c.github.io/aria-in-html/
|
||||
[html-accessibility-url]: http://www.html5accessibility.com/
|
||||
|
||||
@@ -0,0 +1,115 @@
|
||||
# Direct manipulation
|
||||
|
||||
It is sometimes necessary to make changes directly to a component without using
|
||||
state/props to trigger a re-render of the entire subtree – in the browser, this
|
||||
is done by directly modifying a DOM node. `setNativeProps` is the React Native
|
||||
equivalent to setting properties directly on a DOM node. Use direct
|
||||
manipulation when frequent re-rendering creates a performance bottleneck Direct
|
||||
manipulation will not be a tool that you reach for frequently.
|
||||
|
||||
## `setNativeProps` and `shouldComponentUpdate`
|
||||
|
||||
`setNativeProps` is imperative and stores state in the native layer (DOM,
|
||||
UIView, etc.) and not within your React components, which makes your code more
|
||||
difficult to reason about. Before you use it, try to solve your problem with
|
||||
`setState` and `shouldComponentUpdate`.
|
||||
|
||||
## Avoiding conflicts with the render function
|
||||
|
||||
If you update a property that is also managed by the render function, you might
|
||||
end up with some unpredictable and confusing bugs because anytime the component
|
||||
re-renders and that property changes, whatever value was previously set from
|
||||
`setNativeProps` will be completely ignored and overridden.
|
||||
|
||||
## Why use `setNativeProps` on Web?
|
||||
|
||||
Using `setNativeProps` in web-specific code is required when making changes to
|
||||
`className` or `style`, as these properties are controlled by React Native for
|
||||
Web and setting them directly may cause unintended rendering issues.
|
||||
|
||||
```js
|
||||
setOpacityTo(value) {
|
||||
this._childElement.setNativeProps({
|
||||
style: { opacity: value }
|
||||
})
|
||||
}
|
||||
```
|
||||
|
||||
## Composite components and `setNativeProps`
|
||||
|
||||
Composite components are not backed by a DOM node, so you cannot call
|
||||
`setNativeProps` on them. Consider this example:
|
||||
|
||||
```js
|
||||
const MyButton = (props) => (
|
||||
<View>
|
||||
<Text>{props.label}</Text>
|
||||
</View>
|
||||
)
|
||||
|
||||
const App = () => (
|
||||
<TouchableOpacity>
|
||||
<MyButton label="Press me!" />
|
||||
</TouchableOpacity>
|
||||
)
|
||||
```
|
||||
|
||||
If you run this you will immediately see this error: `Touchable` child must
|
||||
either be native or forward `setNativeProps` to a native component. This occurs
|
||||
because `MyButton` isn't directly backed by a native view whose opacity should
|
||||
be set. You can think about it like this: if you define a component with
|
||||
`React.Component/createClass` you would not expect to be able to set a style
|
||||
prop on it and have that work - you would need to pass the style prop down to a
|
||||
child, unless you are wrapping a native component. Similarly, we are going to
|
||||
forward `setNativeProps` to a native-backed child component.
|
||||
|
||||
## Forward `setNativeProps` to a child
|
||||
|
||||
All we need to do is provide a `setNativeProps` method on our component that
|
||||
calls `setNativeProps` on the appropriate child with the given arguments.
|
||||
|
||||
```js
|
||||
class MyButton extends React.Component {
|
||||
setNativeProps(nativeProps) {
|
||||
this._root.setNativeProps(nativeProps)
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<View ref={component => this._root = component}>
|
||||
<Text>{this.props.label}</Text>
|
||||
</View>
|
||||
)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
You can now use `MyButton` inside of `TouchableOpacity`!
|
||||
|
||||
## `setNativeProps` to clear `TextInput` value
|
||||
|
||||
Another very common use case of `setNativeProps` is to clear the value of a
|
||||
`TextInput`. For example, the following code demonstrates clearing the input
|
||||
when you tap a button:
|
||||
|
||||
```js
|
||||
class App extends React.Component {
|
||||
_handlePress() {
|
||||
this._textInput.setNativeProps({ text: '' })
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<TextInput
|
||||
ref={component => this._textInput = component}
|
||||
style={styles.textInput}
|
||||
/>
|
||||
<TouchableOpacity onPress={this._handlePress.bind(this)}>
|
||||
<Text>Clear text</Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
)
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -0,0 +1,28 @@
|
||||
# Known issues
|
||||
|
||||
## Missing modules and Views
|
||||
|
||||
This is an initial release of React Native for Web, therefore, not all of the
|
||||
views present on iOS/Android are released on Web. We are very much interested in
|
||||
the community's feedback on the next set of modules and views.
|
||||
|
||||
Not all the modules or views for iOS/Android can be implemented on Web. In some
|
||||
cases it will be necessary to use a Web counterpart.
|
||||
|
||||
## Missing component props
|
||||
|
||||
There are properties that do not work across all platforms. All web-specific
|
||||
props are annotated with `(web)` in the documentaiton.
|
||||
|
||||
## Platform parity
|
||||
|
||||
There are some known issues in React Native where APIs could be made more
|
||||
consistent between platforms. For example, React Native for Web includes
|
||||
`ActivityIndicator` and a horizontal `ProgressBar`.
|
||||
|
||||
Other parts of React Native, such as the `Animated` and `PanResponder` APIs,
|
||||
are highly complex and have not yet been ported to React Native for Web. Given
|
||||
the difficulties keeping these APIs in sync with React Native, we'd prefer the
|
||||
APIs to be published as separate npm packages. If not, we will consider a web
|
||||
implementation, possibly using the [Web Animations
|
||||
API/polyfill](https://github.com/web-animations/web-animations-js)
|
||||
@@ -0,0 +1,40 @@
|
||||
# React Native
|
||||
|
||||
This is an experimental feature to support: using community-developed React
|
||||
Native components on the Web; and rendering React Native apps to Web.
|
||||
|
||||
Use a module loader that supports package aliases (e.g., webpack), and alias
|
||||
`react-native` to `react-native-web`.
|
||||
|
||||
```js
|
||||
// webpack.config.js
|
||||
|
||||
module.exports = {
|
||||
resolve: {
|
||||
alias: {
|
||||
'react-native': 'react-native-web'
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Web-specific implementations can use the `*.web.js` naming pattern, which
|
||||
webpack will resolve.
|
||||
|
||||
Minor platform differences can use the `Platform` module.
|
||||
|
||||
```js
|
||||
import { AppRegistry, Platform, StyleSheet } from 'react-native'
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
height: (Platform.OS === 'web') ? 200 : 100
|
||||
})
|
||||
|
||||
AppRegistry.registerComponent('MyApp', () => MyApp)
|
||||
|
||||
if (Platform.OS === 'web') {
|
||||
AppRegistry.runApplication('MyApp', {
|
||||
rootTag: document.getElementById('react-root')
|
||||
});
|
||||
}
|
||||
```
|
||||
@@ -0,0 +1,57 @@
|
||||
# Client and Server rendering
|
||||
|
||||
## Client-side rendering
|
||||
|
||||
```js
|
||||
// client.js
|
||||
|
||||
import React, { AppRegistry } from 'react-native'
|
||||
import MyApp from './MyApp'
|
||||
|
||||
// register the app
|
||||
AppRegistry.registerApp('MyApp', () => MyApp)
|
||||
|
||||
// mount the app within the `rootTag` and run it
|
||||
AppRegistry.runApplication('MyApp', { initialProps, rootTag: document.getElementById('react-root') })
|
||||
|
||||
// DOM render
|
||||
React.render(<div />, document.getElementById('sidebar-app'))
|
||||
|
||||
// Server render
|
||||
React.renderToString(<div />)
|
||||
```
|
||||
|
||||
## Server-side rendering
|
||||
|
||||
Pre-rendering React apps on the server is a key feature for Web applications.
|
||||
React Native for Web extends `AppRegistry` to provide support for server-side
|
||||
rendering.
|
||||
|
||||
```js
|
||||
// server.js
|
||||
|
||||
import React, { AppRegistry } from 'react-native'
|
||||
import MyApp from './MyApp'
|
||||
|
||||
// register the app
|
||||
AppRegistry.registerApp('MyApp', () => MyApp)
|
||||
|
||||
// prerender the app
|
||||
const { html, style } = AppRegistry.prerenderApplication('MyApp', { initialProps })
|
||||
|
||||
// construct full page markup
|
||||
const HtmlShell = (html, style) => (
|
||||
<html>
|
||||
<head>
|
||||
<meta charSet="utf-8" />
|
||||
<meta content="initial-scale=1,width=device-width" name="viewport" />
|
||||
{style}
|
||||
</head>
|
||||
<body>
|
||||
<div id="react-root" dangerouslySetInnerHTML={{ __html: html }} />
|
||||
</body>
|
||||
</html>
|
||||
)
|
||||
|
||||
React.renderToStaticMarkup(<HtmlShell html={html} style={style} />)
|
||||
```
|
||||
+21
-16
@@ -42,7 +42,7 @@ documentation of individual components.
|
||||
|
||||
## Using styles
|
||||
|
||||
All the core components accept a `style` attribute.
|
||||
All the React Native components accept a `style` attribute.
|
||||
|
||||
```js
|
||||
<Text style={styles.text} />
|
||||
@@ -52,20 +52,27 @@ All the core components accept a `style` attribute.
|
||||
A common pattern is to conditionally add style based on a condition:
|
||||
|
||||
```js
|
||||
// either
|
||||
<View style={{
|
||||
...styles.base,
|
||||
...(this.state.active && styles.active)
|
||||
}} />
|
||||
|
||||
// or
|
||||
<View style={[
|
||||
styles.base,
|
||||
this.state.active && styles.active
|
||||
]} />
|
||||
```
|
||||
|
||||
## Composing styles
|
||||
|
||||
In order to let a call site customize the style of your component children, you
|
||||
can pass styles around. Use `View.propTypes.style` and `Text.propTypes.style` in
|
||||
order to make sure only styles are being passed.
|
||||
order to make sure only valid styles are being passed.
|
||||
|
||||
```js
|
||||
export default class List extends React.Component {
|
||||
class List extends React.Component {
|
||||
static propTypes = {
|
||||
style: View.propTypes.style,
|
||||
elementStyle: View.propTypes.style,
|
||||
@@ -108,11 +115,11 @@ class List extends React.Component {
|
||||
return (
|
||||
<View
|
||||
children={children}
|
||||
style={{
|
||||
...this.props.style,
|
||||
style={[
|
||||
this.props.style,
|
||||
// override border-color when scrolling
|
||||
...(isScrolling && { borderColor: 'transparent' })
|
||||
}}
|
||||
isScrolling && { borderColor: 'transparent' }
|
||||
]}
|
||||
/>
|
||||
)
|
||||
}
|
||||
@@ -125,19 +132,17 @@ class List extends React.Component {
|
||||
it does not concern itself with _where_ or _when_ those styles are applied to
|
||||
elements.
|
||||
|
||||
Changing styles in response to device adaptation can be controlled using
|
||||
JavaScript Media Query API's. There are several React libraries that provide a
|
||||
means to do this, e.g.,
|
||||
There are various React libraries wrapping JavaScript Media Query API's, e.g.,
|
||||
[react-media-queries](https://github.com/bloodyowl/react-media-queries),
|
||||
[media-query-fascade](https://github.com/tanem/media-query-facade), or
|
||||
[react-responsive](https://github.com/contra/react-responsive). This approach
|
||||
has the benefit of co-locating breakpoint-specific DOM and style changes.
|
||||
[react-responsive](https://github.com/contra/react-responsive). This has the
|
||||
benefit of co-locating breakpoint-specific DOM and style changes.
|
||||
|
||||
## Pseudo-classes and pseudo-elements
|
||||
|
||||
Pseudo-classes like `:hover` and `:focus` can be implemented with the `onHover`
|
||||
and `onFocus` events. Pseudo-elements are not supported; elements should be
|
||||
used instead.
|
||||
Pseudo-classes like `:hover` and `:focus` can be implemented with the events
|
||||
(e.g. `onFocus`). Pseudo-elements are not supported; elements should be used
|
||||
instead.
|
||||
|
||||
## How it works
|
||||
|
||||
@@ -149,7 +154,7 @@ corresponding `className`'s.
|
||||
By doing this, the total size of the generated CSS is determined by the
|
||||
total number of unique declarations (rather than the total number of rules in
|
||||
the application), making it viable to inline the style sheet when pre-rendering
|
||||
on the server.
|
||||
on the server. Styles are updated if new module bundle are loaded asynchronously.
|
||||
|
||||
JavaScript definition:
|
||||
|
||||
|
||||
Reference in New Issue
Block a user