Skip to content

Update examples and docs to React 0.14 #901

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 13 commits into from
Oct 15, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
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
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