1 | # React Stand-In (Facade) [![build status](https://img.shields.io/travis/thekashey/react-stand-in/master.svg?style=flat-square)](https://travis-ci.org/thekashey/react-stand-in) [![npm version](https://img.shields.io/npm/v/react-stand-in.svg?style=flat-square)](https://www.npmjs.com/package/react-stand-in)
|
2 |
|
3 | A successor of [react-proxy](https://github.com/gaearon/react-proxy), created
|
4 | especially for react-hot-loader case. From API point of view - this **is**
|
5 | react-proxy.
|
6 |
|
7 | The differences from react-proxy:
|
8 |
|
9 | * does not proxy or wrap source component, but inherits from and replaces it.
|
10 | * may replace the base class with the latest class variant.
|
11 | * applies changes made in constructor
|
12 |
|
13 | ### How it works
|
14 |
|
15 | React stand in is a real stand in. To satisfy goal it:
|
16 |
|
17 | 1. Inherits from the base class, keeping the all `real` method in prototype
|
18 | 2. On HMR it **replaces** the class prototype by the new component. Now it
|
19 | inherits from the new class variant.
|
20 | 3. To pass the babel's runtime checks it also replaces prototype of the base
|
21 | class.
|
22 | 4. It copies over all static fields from a new class variant.
|
23 | 5. It creates a new and the old class, checking of some class member are
|
24 | changed, creating the `upgrade` list.
|
25 | 6. On a construction, or unevolded component render it applies the upgrade list.
|
26 |
|
27 | The keys points from here, **you should keep in mind**.
|
28 |
|
29 | * Point 3 means than in es2015 env stand-in WILL have a sideeffect on the base
|
30 | class, **soiling it by the new code**. As long the old class have been just
|
31 | replaced by a new one - this is ok.
|
32 | * Point 6 means than you will always instance the `first` class, and next
|
33 | upgrating it to the last one. There is no way to replace constructor for ES6
|
34 | classes.
|
35 |
|
36 | ## Requirements
|
37 |
|
38 | * React 0.15+
|
39 |
|
40 | ## Usage
|
41 |
|
42 | Intended to be used from hot reloading tools like React Hot Loader.\
|
43 | If you’re an application developer, it’s unlikely you’ll want to use it directly.
|
44 |
|
45 | You will need something like
|
46 | [react-deep-force-update](https://github.com/gaearon/react-deep-force-update) to
|
47 | re-render the component tree after applying the update.
|
48 |
|
49 | ```js
|
50 | import React, { Component } from 'react'
|
51 |
|
52 | class ComponentVersion1 extends Component {
|
53 | render() {
|
54 | return <div>Before hot update.</div>
|
55 | }
|
56 | }
|
57 |
|
58 | class ComponentVersion2 extends Component {
|
59 | render() {
|
60 | return <div>After hot update.</div>
|
61 | }
|
62 | }
|
63 | ```
|
64 |
|
65 | Without React Proxy:
|
66 |
|
67 | ```js
|
68 | const rootEl = document.getElementById('root')
|
69 | React.render(<ComponentVersion1 />, rootEl)
|
70 |
|
71 | // Will reset state and kill DOM :-(
|
72 | React.render(<ComponentVersion2 />, rootEl)
|
73 | ```
|
74 |
|
75 | With React Facade:
|
76 |
|
77 | ```js
|
78 | import React from 'react'
|
79 | import { render } from 'react-dom'
|
80 | import createProxy from 'react-stand-in'
|
81 | import deepForceUpdate from 'react-deep-force-update'
|
82 |
|
83 | // Create a proxy object, given the initial React component class.
|
84 | const proxy = createProxy(ComponentVersion1)
|
85 |
|
86 | // Obtain a React class that acts exactly like the initial version.
|
87 | // This is what we'll use in our app instead of the real component class.
|
88 | const Proxy = proxy.get()
|
89 |
|
90 | // Render the component (proxy, really).
|
91 | const rootInstance = render(<Proxy />, rootEl)
|
92 |
|
93 | // Point the proxy to the new React component class by calling update().
|
94 | // Instances will stay mounted and their state will be intact, but their methods will be updated.
|
95 | proxy.update(ComponentVersion2)
|
96 |
|
97 | // Force-update the whole React component tree.
|
98 | // Until React provides an official DevTools API to do this,
|
99 | // you should keep the reference to the root instance(s).
|
100 | deepForceUpdate(rootInstance)
|
101 | ```
|
102 |
|
103 | ## Features (~99% React-proxy)
|
104 |
|
105 | * Supports only modern (ES6 classes) style
|
106 | * Supports inherited and base classes (although you shouldn’t use inheritance
|
107 | with React)
|
108 | * Contains an extensive test suite to avoid regressions
|
109 | * Preserves `displayName`
|
110 | * Preserves enumerability and writability of methods
|
111 | * Preserves `toString()` of methods
|
112 | * Replaces instance getters and setters
|
113 | * Replaces instance methods preserving their identity
|
114 | * Replaces bound instance methods preserving their identity
|
115 | * Because identity is preserved, instance methods already scheduled for
|
116 | `setInterval` or `setTimeout` are updated
|
117 | * Replaces static getters and setters
|
118 | * Replaces unbound static methods
|
119 | * Replaces static properties unless they were overwritten by code
|
120 | * Sets up `this.constructor` to match the most recent class
|
121 |
|
122 | ## License
|
123 |
|
124 | MIT
|