Skip to content

Commit

Permalink
Merge pull request #1122 from gaearon/red-box
Browse files Browse the repository at this point in the history
New `hot` API
  • Loading branch information
theKashey authored Dec 13, 2018
2 parents 5d715a7 + ca92718 commit f15b108
Show file tree
Hide file tree
Showing 41 changed files with 970 additions and 384 deletions.
3 changes: 2 additions & 1 deletion .eslintignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@ examples/
babel.js
index.js
patch.js
webpack.js
webpack.js
root.js
11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,17 @@

All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.

<a name="4.5.3"></a>
## [4.5.3](https://github.com/gaearon/react-hot-loader/compare/v4.5.2...v4.5.3) (2018-12-07)


### Bug Fixes

* enable class equality, but disable class merge, when not hot ([8d214b3](https://github.com/gaearon/react-hot-loader/commit/8d214b3))
* react-dom hot-replacement is too active ([8827a40](https://github.com/gaearon/react-hot-loader/commit/8827a40))



<a name="4.5.2"></a>
## [4.5.2](https://github.com/gaearon/react-hot-loader/compare/v4.5.1...v4.5.2) (2018-12-06)

Expand Down
87 changes: 73 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,10 @@ npm install react-hot-loader

Latest (4.5.0+, beta) version of React-Hot-Loader could be quite 🔥!

> RHL will patch React, React-DOM and work with fiber directly
> RHL will patch React, replace React-DOM by React-🔥-DOM and work with fiber directly
* (required) [use webpack plugin](https://github.com/gaearon/react-hot-loader#webpack-plugin) to let RHL patch React-DOM for you.
* (alternative) [use react-🔥-dom](https://github.com/gaearon/react-hot-loader#react-hot-dom) to use already patched React-DOM.
* (optional) [set configuration](https://github.com/gaearon/react-hot-loader#setconfigconfig) to `ignoreSFC:true` (this will fix `hook`)
* (optional) [set configuration](https://github.com/gaearon/react-hot-loader#setconfigconfig) to `pureRender:true` (this will remove side effect from Classes)

Expand Down Expand Up @@ -60,11 +61,17 @@ setConfig({

```js
// App.js
import React from 'react'
import { hot } from 'react-hot-loader'

import { hot } from 'react-hot-loader/root'
const App = () => <div>Hello World!</div>
export default hot(App)
```

There is also old version of `hot`, used prior version 4.5.4. **Please use a new one**,
as long is it much more resilient to js errors you may make during development.

```js
import { hot } from 'react-hot-loader'
const App = () => <div>Hello World!</div>
export default hot(module)(App)
```

Expand Down Expand Up @@ -241,6 +248,35 @@ module.exports = {
}
```

Webpack plugin will also land a "hot" patch to react-dom, making React-Hot-Loader more compliant to [the principles](https://github.com/gaearon/react-hot-loader/issues/1118).

## React-🔥-Dom

Another way to make RHL more compliant is to use _our_ version of React-Dom - [hot-loader/react-dom](https://github.com/hot-loader/react-dom)

It is the same React-Dom, with the same version, just with our patches already landed inside.

There is 2 ways to install it:

* Use **yarn** name resolution, so `@hot-loader/react-dom` would be installed instead of `react-dom`

```
yarn add @hot-loader/react-dom@npm:react-dom
```

* Use webpack **aliases**

```js
// webpack.conf
...
resolve: {
alias: {
'react-dom': '@hot-loader/react-dom'
}
}
...
```

### Code Splitting

If you want to use Code Splitting + React Hot Loader, the simplest solution is to pick one of our compatible library:
Expand Down Expand Up @@ -563,24 +599,47 @@ ReactDOM.render(<App />, document.getElementById('root'))
Code is automatically patched, you can safely remove `react-hot-loader/patch`
from your webpack config.

### Error reporter is gone
### Error Boundary is inside every component

> Since 4.5.4
On Hot Module Update we will inject `componentDidCatch` and a _special_ `render`
to every Class-based component you have, making [Error Boundaries](https://reactjs.org/docs/error-boundaries.html#introducing-error-boundaries) more local.

React supports error handling out of the box since v16 using `componentDidCatch`. You can create your own [Error Boundary](https://reactjs.org/docs/error-boundaries.html#introducing-error-boundaries) and install it after `hot` has been applied:
After update we will remove all sugar, keeping only Boundaries you've created.

You can provide your own `errorReporter`, via `setConfig({errorReporter})` or opt-out from
root ErrorBoundaries setting `errorBoundary={false}` prop on `AppContainer` or `hot`.
However - this option affects only SFC behavior, and any ClassComponent would boundary itself.

```js
import React from 'react'
import { hot } from 'react-hot-loader'
import { setConfig } from 'react-hot-loader'
import ErrorBoundary from './ErrorBoundary'

const App = () => (
<ErrorBoundary>
<div>Hello world!</div>
</ErrorBoundary>
)
// ErrorBoundary will be given error and errorInfo prop.
setConfig({ errorReporter: ErrorBoundary })
```

export default hot(module)(App)
If `errorReporter` is not set - full screen error overlay would be shown.

#### Setting global Error Reporter

Global Error Reporter would, created a fixed overlay on top the page,
would be used to display errors, not handled by `errorReporter`, and
any HMR error.

You may change, or disable this global error overlay

```js
// to disable
setConfig({ ErrorOverlay: () => null })

// to change
setConfig({ ErrorOverlay: MyErrorOverlay })
```

The UX of existing overlay is a subject to change, and we are open to any proposals.

## Known limitations and side effects

### Note about `hot`
Expand Down
6 changes: 3 additions & 3 deletions examples/all-possible-containers/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,11 @@
"main": "src/index.js",
"scripts": {
"build": "cross-env NODE_ENV=production webpack -p",
"start": "webpack-serve --port 8090 --host 0.0.0.0"
"start": "webpack-serve --port 8080 --host 0.0.0.0"
},
"dependencies": {
"react": "16.3.2",
"react-dom": "16.3.2"
"react": "^16.6.3",
"react-dom": "^16.6.3"
},
"devDependencies": {
"@babel/core": "^7.0.0",
Expand Down
22 changes: 8 additions & 14 deletions examples/all-possible-containers/src/components/App.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// @flow
import { hot } from 'react-hot-loader/root'
import React from 'react'

import Context from '../context'
Expand Down Expand Up @@ -36,20 +37,11 @@ class App extends React.Component {
open: false,
}

componentDidCatch(error, errorInfo) {
this.setState({
error: error,
errorInfo: errorInfo,
})
}

render() {
const { open, error, errorInfo } = this.state
const { A, B } = Secret

return error ? (
<ErrorBoundary error={error} errorInfo={errorInfo} />
) : (
return (
<div>
<React.Fragment>
<fieldset>
Expand Down Expand Up @@ -91,10 +83,12 @@ class App extends React.Component {
let ExportedApp = App

if (__DEV__) {
//const { hot } = require('react-hot-loader');
const { hot, setConfig } = require('react-hot-loader')
setConfig({ logLevel: 'debug' })
ExportedApp = hot(module)(App)
const { setConfig } = require('react-hot-loader')
setConfig({
logLevel: 'debug',
errorReporter: ErrorBoundary,
})
ExportedApp = hot(App)
}

export default ExportedApp
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { EDIT_ME } from './_editMe'

class ChildrenAsFunctionComponent extends React.Component {
render() {
return <div>{this.props.children('passed-argument')}</div>
return <div>{this.props_.children('passed-argument')}</div>
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,11 @@ const ErrorBoundary = ({
<p style={{ color: 'red' }}>{error && error.toString()}</p>
<div>Stacktrace:</div>
<div style={{ color: 'red', marginTop: '10px' }}>
{errorInfo.componentStack
.split('\n')
.map((line, i) => <div key={i}>{line}</div>)}
{errorInfo &&
errorInfo.componentStack &&
errorInfo.componentStack
.split('\n')
.map((line, i) => <div key={i}>{line}</div>)}
</div>
</div>
)
Expand Down
12 changes: 6 additions & 6 deletions examples/all-possible-containers/webpack.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ module.exports = {
devtoolModuleFilenameTemplate: info =>
path.resolve(info.absoluteResourcePath).replace(/\\/g, '/'),
},
devtool: production ? false : 'cheap-module-source-map',
devtool: production ? false : 'eval-source-map',
plugins: [
new webpack.DefinePlugin({
__DEV__: JSON.stringify(!production),
Expand All @@ -36,15 +36,12 @@ module.exports = {
rules: [
{
test: /\.js$/,
use: ['jsx-compress-loader'],
use: ['react-hot-loader/webpack'],
},
{
test: /\.js$/,
exclude: /node_modules/,
use: [
//'react-hot-loader/webpack',
'babel-loader',
],
use: ['babel-loader'],
},
],
},
Expand Down Expand Up @@ -72,6 +69,9 @@ module.exports = {
extensions: ['.ts', '.tsx', '.js', '.jsx'],
alias: {
react: path.resolve(path.join(__dirname, './node_modules/react')),
'react-dom': path.resolve(
path.join(__dirname, './node_modules/react-dom'),
),
'react-hot-loader': path.resolve(
path.join(__dirname, './node_modules/react-hot-loader'),
),
Expand Down
42 changes: 29 additions & 13 deletions examples/all-possible-containers/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -5614,7 +5614,7 @@ promise@^7.1.1:
dependencies:
asap "~2.0.3"

prop-types@^15.6.0, prop-types@^15.6.1:
prop-types@^15.6.1:
version "15.6.1"
resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.6.1.tgz#36644453564255ddda391191fb3a125cbdf654ca"
integrity sha512-4ec7bY1Y66LymSUOH/zARVYObB23AT2h8cf6e/O6ZALB/N0sqZFEx7rq6EYPX2MkOdKORuooI/H5k9TlR4q7kQ==
Expand All @@ -5623,6 +5623,14 @@ prop-types@^15.6.0, prop-types@^15.6.1:
loose-envify "^1.3.1"
object-assign "^4.1.1"

prop-types@^15.6.2:
version "15.6.2"
resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.6.2.tgz#05d5ca77b4453e985d60fc7ff8c859094a497102"
integrity sha512-3pboPvLiWD7dkI3qf3KbUe6hKFKa52w+AE0VCqECtf+QHAKgOL37tTaNCnuX1nAAQ4ZhyP+kYVKf8rLmJ/feDQ==
dependencies:
loose-envify "^1.3.1"
object-assign "^4.1.1"

prr@~1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476"
Expand Down Expand Up @@ -5747,15 +5755,15 @@ rc@^1.0.1, rc@^1.1.6, rc@^1.1.7:
minimist "^1.2.0"
strip-json-comments "~2.0.1"

react-dom@16.3.2:
version "16.3.2"
resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.3.2.tgz#cb90f107e09536d683d84ed5d4888e9640e0e4df"
integrity sha512-MMPko3zYncNrz/7gG17wJWUREZDvskZHXOwbttzl0F0L3wDmToyuETuo/r8Y5yvDejwYcRyWI1lvVBjLJWFwKA==
react-dom@^16.6.3:
version "16.6.3"
resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.6.3.tgz#8fa7ba6883c85211b8da2d0efeffc9d3825cccc0"
integrity sha512-8ugJWRCWLGXy+7PmNh8WJz3g1TaTUt1XyoIcFN+x0Zbkoz+KKdUyx1AQLYJdbFXjuF41Nmjn5+j//rxvhFjgSQ==
dependencies:
fbjs "^0.8.16"
loose-envify "^1.1.0"
object-assign "^4.1.1"
prop-types "^15.6.0"
prop-types "^15.6.2"
scheduler "^0.11.2"

[email protected]:
version "4.3.10"
Expand All @@ -5774,15 +5782,15 @@ react-lifecycles-compat@^3.0.4:
resolved "https://registry.yarnpkg.com/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz#4f1a273afdfc8f3488a8c516bfda78f872352362"
integrity sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==

react@16.3.2:
version "16.3.2"
resolved "https://registry.yarnpkg.com/react/-/react-16.3.2.tgz#fdc8420398533a1e58872f59091b272ce2f91ea9"
integrity sha512-o5GPdkhciQ3cEph6qgvYB7LTOHw/GB0qRI6ZFNugj49qJCFfgHwVNjZ5u+b7nif4vOeMIOuYj3CeYe2IBD74lg==
react@^16.6.3:
version "16.6.3"
resolved "https://registry.yarnpkg.com/react/-/react-16.6.3.tgz#25d77c91911d6bbdd23db41e70fb094cc1e0871c"
integrity sha512-zCvmH2vbEolgKxtqXL2wmGCUxUyNheYn/C+PD1YAjfxHC54+MhdruyhO7QieQrYsYeTxrn93PM2y0jRH1zEExw==
dependencies:
fbjs "^0.8.16"
loose-envify "^1.1.0"
object-assign "^4.1.1"
prop-types "^15.6.0"
prop-types "^15.6.2"
scheduler "^0.11.2"

read-chunk@^2.1.0:
version "2.1.0"
Expand Down Expand Up @@ -6204,6 +6212,14 @@ sax@^1.2.4:
resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9"
integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==

scheduler@^0.11.2:
version "0.11.3"
resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.11.3.tgz#b5769b90cf8b1464f3f3cfcafe8e3cd7555a2d6b"
integrity sha512-i9X9VRRVZDd3xZw10NY5Z2cVMbdYg6gqFecfj79USv1CFN+YrJ3gIPRKf1qlY+Sxly4djoKdfx1T+m9dnRB8kQ==
dependencies:
loose-envify "^1.1.0"
object-assign "^4.1.1"

schema-utils@^0.4.4, schema-utils@^0.4.5:
version "0.4.5"
resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-0.4.5.tgz#21836f0608aac17b78f9e3e24daff14a5ca13a3e"
Expand Down
5 changes: 4 additions & 1 deletion examples/async-components/webpack.config.babel.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ module.exports = {
{
exclude: /node_modules|packages/, // should work without exclude
test: /\.js$/,
use: 'babel-loader',
use: ['react-hot-loader/webpack', 'babel-loader'],
},
],
},
Expand All @@ -25,6 +25,9 @@ module.exports = {
'react-dom': path.resolve(
path.join(__dirname, './node_modules/@hot-loader/react-dom'),
),
'react-hot-loader': path.resolve(
path.join(__dirname, './node_modules/react-hot-loader'),
),
'babel-core': path.resolve(
path.join(__dirname, './node_modules/@babel/core'),
),
Expand Down
2 changes: 1 addition & 1 deletion examples/styled-components/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"version": "1.0.0",
"license": "MIT",
"scripts": {
"start": "webpack-dev-server --hot",
"start": "NODE_ENV=development webpack-dev-server --hot",
"start:prod": "NODE_ENV=production webpack-dev-server --hot"
},
"devDependencies": {
Expand Down
Loading

0 comments on commit f15b108

Please sign in to comment.