Skip to content

Commit

Permalink
Merge pull request #901 from rackt/14
Browse files Browse the repository at this point in the history
Update examples and docs to React 0.14
  • Loading branch information
gaearon committed Oct 15, 2015
2 parents def86ae + 039bc00 commit 5e32583
Show file tree
Hide file tree
Showing 26 changed files with 111 additions and 94 deletions.
5 changes: 3 additions & 2 deletions docs/advanced/ExampleRedditAPI.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,10 @@ This is the complete source code of the Reddit headline fetching example we buil
import 'babel-core/polyfill';

import React from 'react';
import { render } from 'react-dom';
import Root from './containers/Root';

React.render(
render(
<Root />,
document.getElementById('root')
);
Expand Down Expand Up @@ -195,7 +196,7 @@ export default class Root extends Component {
render() {
return (
<Provider store={store}>
{() => <AsyncApp />}
<AsyncApp />
</Provider>
);
}
Expand Down
4 changes: 3 additions & 1 deletion docs/api/applyMiddleware.md
Original file line number Diff line number Diff line change
Expand Up @@ -173,10 +173,12 @@ function makeSandwichesForEverybody() {
// This is very useful for server side rendering, because I can wait
// until data is available, then synchronously render the app.

import { renderToString } from 'react-dom/server';

store.dispatch(
makeSandwichesForEverybody()
).then(() =>
response.send(React.renderToString(<MyApp store={store} />))
response.send(renderToString(<MyApp store={store} />))
);

// I can also dispatch a thunk async action from a component
Expand Down
11 changes: 5 additions & 6 deletions docs/basics/ExampleTodoList.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ This is the complete source code of the tiny todo app we built during the [basic

```js
import React from 'react';
import { render } from 'react-dom';
import { createStore } from 'redux';
import { Provider } from 'react-redux';
import App from './containers/App';
Expand All @@ -16,11 +17,9 @@ import todoApp from './reducers';
let store = createStore(todoApp);

let rootElement = document.getElementById('root');
React.render(
// The child must be wrapped in a function
// to work around an issue in React 0.13.
render(
<Provider store={store}>
{() => <App />}
<App />
</Provider>,
rootElement
);
Expand Down Expand Up @@ -190,7 +189,7 @@ export default connect(select)(App);
#### `components/AddTodo.js`

```js
import React, { findDOMNode, Component, PropTypes } from 'react';
import React, { Component, PropTypes } from 'react';

export default class AddTodo extends Component {
render() {
Expand All @@ -205,7 +204,7 @@ export default class AddTodo extends Component {
}

handleClick(e) {
const node = findDOMNode(this.refs.input);
const node = this.refs.input;
const text = node.value.trim();
this.props.onAddClick(text);
node.value = '';
Expand Down
2 changes: 1 addition & 1 deletion docs/basics/Reducers.md
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ case COMPLETE_TODO:
});
```

Because we want to update a specific item in the array without resorting to mutations, we have to slice it before and after the item. If you find yourself often writing such operations, it’s a good idea to use a helper like [React.addons.update](https://facebook.github.io/react/docs/update.html), [updeep](https://github.com/substantial/updeep), or even a library like [Immutable](http://facebook.github.io/immutable-js/) that has native support for deep updates. Just remember to never assign to anything inside the `state` unless you clone it first.
Because we want to update a specific item in the array without resorting to mutations, we have to slice it before and after the item. If you find yourself often writing such operations, it’s a good idea to use a helper like [react-addons-update](https://facebook.github.io/react/docs/update.html), [updeep](https://github.com/substantial/updeep), or even a library like [Immutable](http://facebook.github.io/immutable-js/) that has native support for deep updates. Just remember to never assign to anything inside the `state` unless you clone it first.

## Splitting Reducers

Expand Down
11 changes: 5 additions & 6 deletions docs/basics/UsageWithReact.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ These are all normal React components, so we won’t stop to examine them in det
#### `components/AddTodo.js`

```js
import React, { findDOMNode, Component, PropTypes } from 'react';
import React, { Component, PropTypes } from 'react';

export default class AddTodo extends Component {
render() {
Expand All @@ -103,7 +103,7 @@ export default class AddTodo extends Component {
}

handleClick(e) {
const node = findDOMNode(this.refs.input);
const node = this.refs.input;
const text = node.value.trim();
this.props.onAddClick(text);
node.value = '';
Expand Down Expand Up @@ -274,6 +274,7 @@ First, we need to import `Provider` from [`react-redux`](http://github.com/gaear

```js
import React from 'react';
import { render } from 'react-dom';
import { createStore } from 'redux';
import { Provider } from 'react-redux';
import App from './containers/App';
Expand All @@ -282,11 +283,9 @@ import todoApp from './reducers';
let store = createStore(todoApp);

let rootElement = document.getElementById('root');
React.render(
// The child must be wrapped in a function
// to work around an issue in React 0.13.
render(
<Provider store={store}>
{() => <App />}
<App />
</Provider>,
rootElement
);
Expand Down
25 changes: 15 additions & 10 deletions docs/recipes/ServerRendering.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,19 +64,21 @@ The first thing that we need to do on every request is create a new Redux store

When rendering, we will wrap `<App />`, our root component, inside a `<Provider>` to make the store available to all components in the component tree, as we saw in [Usage with React](../basics/UsageWithReact.md).

The key step in server side rendering is to render the initial HTML of our component _**before**_ we send it to the client side. To do this, we use [React.renderToString()](https://facebook.github.io/react/docs/top-level-api.html#react.rendertostring).
The key step in server side rendering is to render the initial HTML of our component _**before**_ we send it to the client side. To do this, we use [ReactDOMServer.renderToString()](https://facebook.github.io/react/docs/top-level-api.html#reactdomserver.rendertostring).

We then get the initial state from our Redux store using [`store.getState()`](../api/Store.md#getState). We will see how this is passed along in our `renderFullPage` function.

```js
import { renderToString } from 'react-dom/server';

function handleRender(req, res) {
// Create a new Redux store instance
const store = createStore(counterApp);

// Render the component to a string
const html = React.renderToString(
const html = renderToString(
<Provider store={store}>
{() => <App />}
<App />
</Provider>
);

Expand Down Expand Up @@ -130,6 +132,7 @@ Let’s take a look at our new client file:

```js
import React from 'react';
import { render } from 'react-dom';
import { createStore } from 'redux';
import { Provider } from 'react-redux';
import App from './containers/App';
Expand All @@ -141,17 +144,17 @@ const initialState = window.__INITIAL_STATE__;
// Create Redux store with initial state
const store = createStore(counterApp, initialState);

React.render(
render(
<Provider store={store}>
{() => <App />}
<App />
</Provider>,
document.getElementById('root')
);
```

You can set up your build tool of choice (Webpack, Browserify, etc.) to compile a bundle file into `dist/bundle.js`.

When the page loads, the bundle file will be started up and [`React.render()`](https://facebook.github.io/react/docs/top-level-api.html#react.render) will hook into the `data-react-id` attributes from the server-rendered HTML. This will connect our newly-started React instance to the virtual DOM used on the server. Since we have the same initial state for our Redux store and used the same code for all our view components, the result will be the same real DOM.
When the page loads, the bundle file will be started up and [`ReactDOM.render()`](https://facebook.github.io/react/docs/top-level-api.html#reactdom.render) will hook into the `data-react-id` attributes from the server-rendered HTML. This will connect our newly-started React instance to the virtual DOM used on the server. Since we have the same initial state for our Redux store and used the same code for all our view components, the result will be the same real DOM.

And that’s it! That is all we need to do to implement server side rendering.

Expand All @@ -171,6 +174,7 @@ The request contains information about the URL requested, including any query pa

```js
import qs from 'qs'; // Add this at the top of the file
import { renderToString } from 'react-dom/server';

function handleRender(req, res) {
// Read the counter from the request, if provided
Expand All @@ -184,9 +188,9 @@ function handleRender(req, res) {
const store = createStore(counterApp, initialState);

// Render the component to a string
const html = React.renderToString(
const html = renderToString(
<Provider store={store}>
{() => <App />}
<App />
</Provider>
);

Expand Down Expand Up @@ -231,6 +235,7 @@ On the server side, we simply wrap our existing code in the `fetchCounter` and r
```js
// Add this to our imports
import { fetchCounter } from './api/counter';
import { renderToString } from 'react-dom/server';

function handleRender(req, res) {
// Query our mock API asynchronously
Expand All @@ -246,9 +251,9 @@ function handleRender(req, res) {
const store = createStore(counterApp, initialState);

// Render the component to a string
const html = React.renderToString(
const html = renderToString(
<Provider store={store}>
{() => <App />}
<App />
</Provider>
);

Expand Down
29 changes: 21 additions & 8 deletions docs/recipes/WritingTests.md
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,12 @@ describe('todos reducer', () => {

A nice thing about React components is that they are usually small and only rely on their props. That makes them easy to test.

First, we will install [React Test Utilities](https://facebook.github.io/react/docs/test-utils.html):

```
npm install --save-dev react-addons-test-utils
```

To test the components we make a `setup()` helper that passes the stubbed callbacks as props and renders the component with [React shallow renderer](https://facebook.github.io/react/docs/test-utils.html#shallow-rendering). This lets individual tests assert on whether the callbacks were called when expected.

#### Example
Expand Down Expand Up @@ -290,13 +296,11 @@ can be tested like:

```js
import expect from 'expect';
import jsdomReact from '../jsdomReact';
import React from 'react/addons';
import React from 'react';
import TestUtils from 'react-addons-test-utils';
import Header from '../../components/Header';
import TodoTextInput from '../../components/TodoTextInput';

const { TestUtils } = React.addons;

function setup() {
let props = {
addTodo: expect.createSpy()
Expand All @@ -314,8 +318,6 @@ function setup() {
}

describe('components', () => {
jsdomReact();

describe('Header', () => {
it('should render correctly', () => {
const { output } = setup();
Expand Down Expand Up @@ -363,7 +365,18 @@ global.window = document.defaultView;
global.navigator = global.window.navigator;
```

It’s important that this code is evaluated *before* React is imported. To ensure this, modify your `mocha` command to include `--require ./test/setup.js` in the options.
It’s important that this code is evaluated *before* React is imported. To ensure this, modify your `mocha` command to include `--require ./test/setup.js` in the options in your `package.json`:

```js
{
...
"scripts": {
...
"test": "mocha --compilers js:babel/register --recursive --require ./test/setup.js",
},
...
}
```

### Connected Components

Expand Down Expand Up @@ -475,7 +488,7 @@ describe('middleware', () => {

### Glossary

- [React Test Utils](http://facebook.github.io/react/docs/test-utils.html): Test utilities that ship with React.
- [React Test Utils](http://facebook.github.io/react/docs/test-utils.html): Test Utilities for React.

- [jsdom](https://github.com/tmpvar/jsdom): A plain JavaScript implementation of the DOM API. jsdom allows us to run the tests without browser.

Expand Down
5 changes: 3 additions & 2 deletions examples/async/index.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
import 'babel-core/polyfill';
import React from 'react';
import { render } from 'react-dom';
import { Provider } from 'react-redux';
import App from './containers/App';
import configureStore from './store/configureStore';

const store = configureStore();

React.render(
render(
<Provider store={store}>
{() => <App />}
<App />
</Provider>,
document.getElementById('root')
);
5 changes: 3 additions & 2 deletions examples/async/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,9 @@
"homepage": "http://rackt.github.io/redux",
"dependencies": {
"isomorphic-fetch": "^2.1.1",
"react": "^0.13.3",
"react-redux": "^2.1.2",
"react": "^0.14.0",
"react-dom": "^0.14.0",
"react-redux": "^4.0.0",
"redux": "^3.0.0",
"redux-logger": "^2.0.2",
"redux-thunk": "^0.1.0"
Expand Down
5 changes: 3 additions & 2 deletions examples/counter/index.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import React from 'react';
import { render } from 'react-dom';
import { Provider } from 'react-redux';
import App from './containers/App';
import configureStore from './store/configureStore';

const store = configureStore();

React.render(
render(
<Provider store={store}>
{() => <App />}
<App />
</Provider>,
document.getElementById('root')
);
6 changes: 4 additions & 2 deletions examples/counter/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,9 @@
},
"homepage": "http://rackt.github.io/redux",
"dependencies": {
"react": "^0.13.3",
"react-redux": "^2.1.2",
"react": "^0.14.0",
"react-dom": "^0.14.0",
"react-redux": "^4.0.0",
"redux": "^3.0.0",
"redux-thunk": "^0.1.0"
},
Expand All @@ -31,6 +32,7 @@
"jsdom": "^5.6.1",
"mocha": "^2.2.5",
"node-libs-browser": "^0.5.2",
"react-addons-test-utils": "^0.14.0",
"react-transform-hmr": "^1.0.0",
"webpack": "^1.9.11",
"webpack-dev-middleware": "^1.2.0",
Expand Down
11 changes: 4 additions & 7 deletions examples/counter/test/components/Counter.spec.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import expect from 'expect';
import React from 'react/addons';
import React from 'react';
import TestUtils from 'react-addons-test-utils';
import Counter from '../../components/Counter';

const { TestUtils } = React.addons;

function setup() {
const actions = {
increment: expect.createSpy(),
Expand All @@ -15,10 +14,8 @@ function setup() {
return {
component: component,
actions: actions,
buttons: TestUtils.scryRenderedDOMComponentsWithTag(component, 'button').map(button => {
return button.getDOMNode();
}),
p: TestUtils.findRenderedDOMComponentWithTag(component, 'p').getDOMNode()
buttons: TestUtils.scryRenderedDOMComponentsWithTag(component, 'button'),
p: TestUtils.findRenderedDOMComponentWithTag(component, 'p')
};
}

Expand Down
Loading

0 comments on commit 5e32583

Please sign in to comment.