Skip to content
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

[WIP] Repository Documentation (non-gh-pages) #257

Merged
merged 24 commits into from
Nov 20, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
4e2c4ac
Removed starter kits from docs/README.md
hedgerh Apr 22, 2016
84a1f5a
Removed old documentation.
hedgerh Apr 22, 2016
5d551eb
Migration guide. Announcement on main README
hedgerh Apr 22, 2016
eec6532
Cleaned up the top of README.md
hedgerh Apr 22, 2016
b29375c
docs: early draft
gadicc Apr 25, 2016
27bd7e0
fix broken render statements
gadicc Apr 25, 2016
8ab36b5
fix closing parenthesis on require statements
gadicc Apr 26, 2016
d0634a4
require().default for ES6 modules
gadicc Apr 26, 2016
e043b10
Adding additional clarification to RHL3 docs along with JSX highlight…
Apr 26, 2016
77dd1db
Updating syntax in example(s) to be consistent ES6
Apr 26, 2016
1296c3f
Merge pull request #258 from tsaiDavid/next-docs
gadicc Apr 26, 2016
1a7f493
restore original README so we can cleanly merge in hedgerh's changes
gadicc Apr 26, 2016
5edf7bd
Merge remote-tracking branch 'hedgerh/docs-migration' into next-docs
gadicc Apr 26, 2016
ee4f18d
Add Tips & Tricks doc
gadicc Apr 26, 2016
6f2c583
consoleErrorReporter: correct error proptype & npm i redbox-react
gadicc May 3, 2016
26f4c14
Fixing the broken V3 example in the docs
jameskraus Aug 23, 2016
123d940
Merge pull request #349 from jameskraus/next-docs
calesce Sep 3, 2016
574a410
Add "Known Limitations" doc
calesce Oct 19, 2016
142201d
Add System.import section on known limitations
calesce Oct 19, 2016
644d4f3
Merge pull request #402 from calesce/known-limitations
hedgerh Oct 19, 2016
9da8e84
document migrating from create-react-app
calesce Oct 31, 2016
d2706c6
Update README.md
calesce Nov 2, 2016
61582ed
update Known Limitations doc
calesce Nov 5, 2016
8365f09
Update README.md
calesce Nov 12, 2016
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
28 changes: 21 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,28 @@
# React Hot Loader [![npm package](https://img.shields.io/npm/v/react-hot-loader.svg?style=flat-square)](https://www.npmjs.org/package/react-hot-loader)
# React Hot Loader 3 [![npm package](https://img.shields.io/npm/v/react-hot-loader.svg?style=flat-square)](https://www.npmjs.org/package/react-hot-loader)

### React Hot Loader 3 has arrived!

It fixes some long-standing issues with both React Hot Loader and React Transform.

**It is intended as a replacement for both.**

Some nice things about it:

* Editing functional components preserves state
* Works great with higher order components
* Requires little configuration
* Automatically disabled in production
* Works with or without Babel (you can remove `react-hot-loader/babel` from `.babelrc` and instead add `react-hot-loader/webpack` to `loaders`)

Check out [the Migration to 3.0 guide](https://github.com/gaearon/react-hot-loader/tree/master/docs#migration-to-30) to learn how to migrate your app to 3.0.

### Learn

This is a **stable for daily use in development** implementation of [React live code editing](http://www.youtube.com/watch?v=pw4fKkyPPg8).

* Get inspired by a **[demo video](https://vimeo.com/100010922)** and **[try the live demo](http://gaearon.github.io/react-hot-loader/)**.

* Read **[the integration walkthrough](http://gaearon.github.io/react-hot-loader/getstarted/).**
* Read **[the Getting Started guide](http://gaearon.github.io/react-hot-loader/getstarted/).**

* Use **[one of the starter kits](https://github.com/gaearon/react-hot-loader/tree/master/docs#starter-kits)** for your next React project.

Expand All @@ -27,14 +45,10 @@ To use React Hot Loader in an existing project, you need to
* enable Hot Module Replacement, which is a Webpack feature;
* configure Webpack to use React Hot Loader for JS or JSX files.

These steps are covered by **[the walkthrough](http://gaearon.github.io/react-hot-loader/getstarted/)**.
These steps are covered by **[the Getting Started guide](http://gaearon.github.io/react-hot-loader/getstarted/)**.

If you'd rather stay with **Browserify**, check out **[LiveReactload](https://github.com/milankinen/livereactload)** by Matti Lankinen.

## Flux

**[Redux](https://github.com/gaearon/redux)** is a Flux implementation that supports hot reloading of everything out of the box. Read **[The Evolution of Flux Frameworks](https://medium.com/@dan_abramov/the-evolution-of-flux-frameworks-6c16ad26bb31)** for some context around its creation.

## React Native

You can use React Hot Loader to tweak a React Native application. Check out **[react-native-webpack-server](https://github.com/mjohnston/react-native-webpack-server)** by Michael Johnston.
Expand Down
62 changes: 62 additions & 0 deletions docs/Known Limitations.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
## Known Limitations

### Code Splitting
If you want to use Webpack code splitting via `require.ensure`, you'll need to add an additional `module.hot.accept` callback within the `require.ensure` block, like this:

```js
require.ensure([], (require) => {
if (module.hot) {
module.hot.accept('../components/App', () => {
loadComponent(require('../components/App').default);
})
}
loadComponent(require('../components/App').default);
});
```

Note that if you're using React Router (pre-4.0), this will only work with `getChildRoutes`, but not `getComponent`, since `getComponent`'s callback will only load a component once.

Also, if you're using the Webpack 2 beta, you can use `System.import` without extra `module.hot.accept` calls, although there are still a [few issues with it](https://github.com/gaearon/react-hot-loader/issues/303).

### Checking Element `type`s
Because React Hot Loader creates proxied versions of your components, comparing reference types of elements won't work:

```jsx
const element = <Component />;
console.log(element.type === Component); // false
```

One workaround is to create an element (that will have the `type` of the proxied component):

```jsx
const ComponentType = (<Component />).type;
const element = <Component />;
console.log(element.type === ComponentType); // true
```

You can also set a property on the component class:

```jsx
const Widget = () => <div>hi</div>;
Widget.isWidgetType = true;
console.log(<Widget />.type.isWidgetType); // true
```

### Reassigning Components
React Hot Loader will only try to reload the original component reference, so if you reassign it to another variable like this:

```jsx
let App = () => (<div>hello</div>);
App = connect()(App);
export default App;
```

React Hot Loader won't reload it. Instead, you'll need to define it once:

```jsx
const App = () => (<div>hello</div>);
export default connect()(App);
```

### Decorators
Components that are decorated (using something like [`@autobind`](https://github.com/andreypopp/autobind-decorator)) currently do not retain state when being hot-reloaded. (see [#279](https://github.com/gaearon/react-hot-loader/issues/279))
173 changes: 91 additions & 82 deletions docs/README.md
Original file line number Diff line number Diff line change
@@ -1,107 +1,120 @@
### Starter Kits
### Starter Kit
* [react-hot-boilerplate](https://github.com/gaearon/react-hot-boilerplate/tree/next) (Bare minimum)

* [react-hot-boilerplate](https://github.com/gaearon/react-hot-boilerplate) (Bare minimum)
* [react-starter](https://github.com/webpack/react-starter) (react-router, includes production configs)
* [isomorphic-hot-loader](https://github.com/irvinebroque/isomorphic-hot-loader) (react-router, isomorphic)
* [isomorphic-react-template](https://github.com/gpbl/isomorphic-react-template/) (react-router, isomorphic)
* [coffee-react-quickstart](https://github.com/KyleAMathews/coffee-react-quickstart) (react-router, CoffeeScript, Gulp)
* [react-static-boilerplate](https://github.com/koistya/react-static-boilerplate) (static site generator; React, PostCSS, Webpack, BrowserSync)
* [boilerplate-webpack-react](https://github.com/tcoopman/boilerplate-webpack-react) (react-router, isomorphic)
* [este](http://github.com/steida/este) (react-router, isomorphic, Flux, Babel)
* [react-isomorphic-starterkit](https://github.com/RickWong/react-isomorphic-starterkit) (react-router, react-async, isomorphic)
* [yarsk](https://github.com/bradleyboy/yarsk) (Babel, Karma + Mocha, automated publishing to GitHub pages)
* [react-web](https://github.com/darul75/web-react) (Babel, react-router, Alt flux)
* [esnext-quickstart](https://github.com/nkbt/esnext-quickstart) (compile-time ESLint, ES6, Babel, Karma + Jasmine + Coverage)
* [react-webpack-boilerplate](https://github.com/srn/react-webpack-boilerplate) (One-click Heroku deployable, Node.js server)
* [flask-react-boilerplate](https://github.com/alexkuz/flask-react-boilerplate) (One-click Heroku deployable, Flask server + PostgreSQL, Babel, Flummox)
* [react-kickstart](https://github.com/vesparny/react-kickstart) (react-router, mocha + chai + istanbul)
* [react-redux-universal-hot-example](https://github.com/erikras/react-redux-universal-hot-example) (isomorphic, redux, client and server async data fetching, babel, react-router)
* [go-starter-kit](https://github.com/olebedev/go-starter-kit) (hot reloadable golang/react/flummox/css-module isomorphic starter kit)
* [react-fullstack-skeleton](https://github.com/fortruce/react-fullstack-skeleton) (react w/ backend api server)

Don't be shy, add your own.

### Migrating to 1.0

React Hot Loader has reached 1.0, and it's a breaking change. When React Hot Loader just started, it used a regex to find `createClass` calls and replace them with its own implementation. This turned out to be a bad idea for a number of reasons:

* Doesn't work when components are created through wrappers (e.g. [OmniscientJS](http://omniscientjs.github.io));
* Doesn't work when author calls React differently;
* Causes false positives in React source code comments and elsewhere;
* Most importantly, won't work with ES6 classes that will be future of React.

Here's how we're solving these problems in 1.0:

#### Only `module.exports` and its own properties are hot by default

With 1.0, we no longer parse your sources. Instead, we only now make `module.exports` and its [own properties](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/hasOwnProperty) hot by default, and only if their prototype declares `render` method or descends from `React.Component`. **If you've been splitting each component in a separate file, that means no change for you here!** This allows us to support exotic wrappers.

If you use inheritance in React 0.13, base classes will only be opted into hot reloading if they descend from `React.Component` or define `render` method. Otherwise you need to explicitly call `module.makeHot` as described below.

#### You can make hot anything else via opt-in `module.makeHot` API

But what if you *want* to have several hot-reloadable components in one file? Or what if you want to export a function creating components, or an object with several components as properties? For that, 1.0 **adds first public API to hot loader: `module.makeHot`**. This method will be present on `module` object if hot loader is enabled, and allows you to make any component hot:
### Migration to 3.0
- If you're using Babel and ES6, remove the `react-hot` loader from any loaders in your Webpack config, and add `react-hot-loader/babel` to the `plugins` section of your `.babelrc`:

```js
var Something = React.createClass({
...
};

if (module.makeHot) { // Won't be true in production
Something = module.makeHot(Something);
{
"presets": ["es2015-loose", "stage-0", "react"],
"plugins": ["react-hot-loader/babel"]
}
```

Explicit API can also be used inside functions:
- If you're *not* using Babel, or you're using Babel without ES6, replace the `react-hot` loader in your Webpack config with `react-hot-loader/webpack`:

```js
function generateClass(param) {
var Class = return React.createClass({
...
};

if (module.makeHot) {
Class = module.makeHot(Class, param);
}

return Class;
{
test: /\.js$/,
loaders: ['react-hot', 'babel'],
include: path.join(__dirname, '..', '..', 'src')
}

// becomes
{
test: /\.js$/,
loaders: ['react-hot-loader/webpack', 'babel'],
include: path.join(__dirname, '..', '..', 'src')
}
```

Note the second parameter: `makeHot` needs some way to distinguish components of same type inside on module. By default, it uses `displayName` of given component class, but in case of dynamically generated classes (or if you're not using JSX), you have to provide it yourself.
- 'react-hot-loader/patch' should be placed at the top of the `entry` section in your Webpack config. An error will occur if any code runs before `react-hot-loader/patch` has, so put it in the first position.

### Manual mode (experimental)
- `<AppContainer/>` is a component that handles module reloading, as well as error handling. The root component of your app should be nested in AppContainer as a child. When in production, AppContainer is automatically disabled, and simply returns its children.

You can now use `react-hot?manual` instead of `react-hot` in Webpack config to turn on manual mode. In manual mode, “accepting” hot updates is up to you; modules won't accept themselves automatically. This can be used, for example, to put reloading logic on very top of the application and [hot-reload routes as well as components](https://github.com/rackt/react-router/pull/606#issuecomment-66936975). It will also work better when you have a lot of modules that export component-generating functions because updates will propagate to the top. (Don't worry if you don't understand this; it's just something experimental you might want to try to integrate hot reloading deeper into your app.)
- React Hot Loader 3 does not hide the hot module replacement API, so the following needs to be added below wherever you call `ReactDOM.render` in your app:

### Usage with external React
```jsx
import React from 'react'
import ReactDOM from 'react-dom'
import { AppContainer } from 'react-hot-loader'
import App from './containers/App'

If you're using external standalone React bundle instead of NPM package, Hot Loader will fail because it relies on `react/lib/ReactMount` which is not exposed in precompiled React. It needs `ReactMount` to keep track of mounted React component instances on the page. However, you can supply your own root instance provider:
ReactDOM.render(
<AppContainer>
<App/>
</AppContainer>,
document.getElementById('root')
);

```js
// Your app's index.js
// Hot Module Replacement API
if (module.hot) {
module.hot.accept('./containers/App', () => {
const NextApp = require('./containers/App').default;
ReactDOM.render(
<AppContainer>
<NextApp/>
</AppContainer>,
document.getElementById('root')
);
});
}
```

You can also check out [this commit for the migration of a TodoMVC app from 1.0 to 3.0.](https://github.com/gaearon/redux-devtools/commit/64f58b7010a1b2a71ad16716eb37ac1031f93915)

## Migrating from [create-react-app](https://github.com/facebookincubator/create-react-app)

* Run `npm run eject`
* Install React Hot Loader (`npm install --save-dev react-hot-loader@3.0.0-beta.6`)
* In `config/webpack.config.dev.js`:
1. Add `'react-hot-loader/patch'` to entry array (anywhere before `paths.appIndexJs`). It should now look like (excluding comments):
```js
entry: [
'react-hot-loader/patch',
require.resolve('react-dev-utils/webpackHotDevClient'),
require.resolve('./polyfills'),
paths.appIndexJs
]
```

2. Add `'react-hot-loader/babel'` to Babel loader configuration. The loader should now look like:
```js
{
test: /\.(js|jsx)$/,
include: paths.appSrc,
loader: 'babel',
query: {
cacheDirectory: findCacheDir({
name: 'react-scripts'
}),
plugins: [
'react-hot-loader/babel'
]
}
}
```

var React = require('react'),
router = require('./router');
* Add `AppContainer` to `src/index.js` (see `AppContainer` section in [Migration to 3.0 above](https://github.com/gaearon/react-hot-loader/blob/next-docs/docs/README.md#migration-to-30))

var rootInstance = null;
## Webpack 2

router.run(function (Handler, state) {
rootInstance = React.render(<Handler />, document.body);
});
Because Webpack 2 has built-in support for ES2015 modules, you won't need to re-require your app root in `module.hot.accept`. The example above becomes:

```jsx
if (module.hot) {
require('react-hot-loader/Injection').RootInstanceProvider.injectProvider({
getRootInstances: function () {
// Help React Hot Loader figure out the root component instances on the page:
return [rootInstance];
}
module.hot.accept('./containers/App', () => {
ReactDOM.render(
<AppContainer>
<App/>
</AppContainer>,
document.getElementById('root')
);
});
}
```

You'll only need this if you [use a precompiled version of React](https://github.com/gaearon/react-hot-loader/issues/53). If you use React NPM package, this is not necessary. You should generally use React NPM package unless you have good reason not to.
To make this work, you'll need to opt out of Babel transpiling ES2015 modules by changing the Babel ES2015 preset to be `["es2015", { "modules": false }]`

### Source Maps

Expand All @@ -110,7 +123,3 @@ If you use `devtool: 'source-map'` (or its equivalent), source maps will be emit
Source maps slow down your project. Use `devtool: 'eval'` for best build performance.

Hot reloading code is just one line in the beginning and one line in the end of each module so you might not need source maps at all.

### React Hot API

If you're authoring a build tool, you might be interested to hear that React Hot Loader brains have been extracted into runtime-agnostic [React Hot API](https://github.com/gaearon/react-hot-api). React Hot Loader just binds that API to Webpack runtime, but you can implement yours too.
26 changes: 26 additions & 0 deletions docs/TipsAndTricks.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Tips and Tricks

**How to get an error in your console too:**

The `Redbox` errors are great to clearly see rendering issues, and avoiding an uncaught error from breaking your app. But there are some advantages to a thrown error in the console too, like filename resolution via sourcemaps, and click-to-open. To get the best of both worlds, modify your app entry point as follows:

```jsx
import Redbox from 'redbox-react';

const consoleErrorReporter = ({error}) => {
console.error(error);
return <Redbox error={error} />;
};

consoleErrorReporter.propTypes = {
error: React.PropTypes.instanceOf(Error).isRequired
};

render((
<AppContainer errorReporter={consoleErrorReporter}>
<AppRoot />
</AppContainer>
), document.getElementById('react-root'));
```

You'll also need to `npm install --save-dev redbox-react`.