├── .babelrc
├── .gitignore
├── .prettierrc
├── LICENSE
├── README.md
├── initTests.js
├── package-lock.json
├── package.json
├── reacts
├── 0.14.9
│ ├── index.js
│ └── package.json
├── 15.0
│ ├── index.js
│ └── package.json
├── 15.1
│ ├── index.js
│ └── package.json
├── 15.2
│ ├── index.js
│ └── package.json
├── 15.3
│ ├── index.js
│ └── package.json
├── 15.4
│ ├── index.js
│ └── package.json
├── 15.5
│ ├── index.js
│ └── package.json
├── 15.6
│ ├── index.js
│ └── package.json
├── 16.0
│ ├── index.js
│ └── package.json
├── 16.1
│ ├── index.js
│ └── package.json
├── 16.2
│ ├── index.js
│ └── package.json
└── 16.3
│ ├── index.js
│ └── package.json
├── src
├── RefForwarder.js
├── __tests__
│ ├── createRef.test.js
│ ├── forwardRef.test.js
│ └── getRef.test.js
├── createRef.js
├── forwardRef.js
├── getRef.js
└── index.js
└── test-utils
├── installReactVersions.js
└── withReact.js
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": [
3 | [
4 | "env",
5 | {
6 | "loose": true,
7 | "targets": {
8 | "browsers": [
9 | "last 2 versions",
10 | "ie >= 9"
11 | ]
12 | }
13 | }
14 | ],
15 | "react",
16 | "flow"
17 | ],
18 | "plugins": [
19 | "transform-class-properties",
20 | "add-module-exports"
21 | ]
22 | }
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 |
8 | # Runtime data
9 | pids
10 | *.pid
11 | *.seed
12 | *.pid.lock
13 |
14 | # Directory for instrumented libs generated by jscoverage/JSCover
15 | lib-cov
16 |
17 | # Coverage directory used by tools like istanbul
18 | coverage
19 |
20 | # nyc test coverage
21 | .nyc_output
22 |
23 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
24 | .grunt
25 |
26 | # Bower dependency directory (https://bower.io/)
27 | bower_components
28 |
29 | # node-waf configuration
30 | .lock-wscript
31 |
32 | # Compiled binary addons (http://nodejs.org/api/addons.html)
33 | build/Release
34 |
35 | # Dependency directories
36 | node_modules/
37 | jspm_packages/
38 |
39 | # Typescript v1 declaration files
40 | typings/
41 |
42 | # Optional npm cache directory
43 | .npm
44 |
45 | # Optional eslint cache
46 | .eslintcache
47 |
48 | # Optional REPL history
49 | .node_repl_history
50 |
51 | # Output of 'npm pack'
52 | *.tgz
53 |
54 | # Yarn Integrity file
55 | .yarn-integrity
56 |
57 | # dotenv environment variables file
58 | .env
59 |
60 | lib
61 | .DS_Store
62 |
63 |
--------------------------------------------------------------------------------
/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "singleQuote": true
3 | }
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018-present Justin Hines
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # create-react-ref
2 |
3 | ## What is this?
4 |
5 | React version 16.3 introduces 2 new APIs, `React.createRef` ([React RFC #17](https://github.com/reactjs/rfcs/blob/master/text/0017-new-create-ref.md)) and `React.forwardRef` ([React RFC #30](https://github.com/reactjs/rfcs/blob/master/text/0030-ref-forwarding.md)).
6 |
7 | This lib was created to allow using the new ref APIs without an immediate upgrade. Once upgraded to React 16.3, you should be able to remove this lib from your imports and just import React's version. However, this lib also checks for React's version and, if it is installed, it will use it instead of the polyfilled version. This way, you can remove the polyfill when you're ready and not at the same time that you upgrade.
8 |
9 | #### This project is not recommended for libraries if you intend to expose the component whose ref is fowarded. The reason is that if your users use a version of React before 16.3, they will receive the internal `RefForwarder` component of this package. This package was created to allow users to use the new API as long as the user is the creator and consumer of the forwarding ref. While there is a method in this lib that will always grab the correct ref `getRef`, it is not a good idea to ask your users to depend on and use this package. If you want to forward refs, you may want to fallback to using an additional prop, for example `inputRef`.
10 |
11 | ## How to install
12 |
13 | NPM:
14 |
15 | ```
16 | npm install create-react-ref
17 | ```
18 |
19 | YARN:
20 |
21 | ```
22 | yarn add create-react-ref
23 | ```
24 |
25 | You'll need to also have `react` installed
26 |
27 | ## API and examples
28 |
29 | ### createRef()
30 |
31 | The `createRef` API returns an object which attaches the ref to a `current` property. The polyfill works by returning a function which when invoked internall by React with the ref, will attach it to a `current` property or the function.
32 |
33 | ```javascript
34 | import createRef from 'create-react-ref/lib/createRef';
35 |
36 | class MyComponent extends React.Component {
37 | // Once input ref is mounted, it is accessed
38 | // under the `current` proprty
39 | inputRef = createRef();
40 |
41 | render() {
42 | return (
43 |
44 |
45 |
46 | );
47 | }
48 |
49 | componentDidMount() {
50 | this.inputRef.current.focus();
51 | }
52 | }
53 | ```
54 |
55 | ### forwardRef(render)
56 |
57 | The `forwardRef` API allows forwarding refs to a child (inner) component when a ref is attached to the parent (outer) component.
58 | Arguments
59 |
60 | * [`render(props, ref)`: `ReactElement`]: Render should be a function that when called returns a ReactElement to render. It gets passed the current `props` and the `ref` to foward. Attach the `ref` to the inner child component's ref prop that you want a user to receive when attaching a ref to the outer component.
61 |
62 | ```javascript
63 | import forwardRef from 'create-react-ref/lib/forwardRef';
64 | import createRef from 'create-react-ref/lib/createRef';
65 |
66 | const ThemeContext = React.createContext('light');
67 |
68 | // Example HOC
69 | function withTheme(ThemedComponent) {
70 | function ThemeContextInjector(props) {
71 | return (
72 |
73 | {value => (
74 |
75 | )}
76 |
77 | );
78 | }
79 |
80 | // Forward refs through to the inner, "themed" component:
81 | return forwardRef((props, ref) => (
82 |
83 | ));
84 | }
85 |
86 | const ThemedButton = withTheme(Button);
87 | // For the polyfilled forwardRef, you must use `createRef`.
88 | const buttonRef = createRef();
89 |
90 | // buttonRef.current will point to ThemedButton, rather than ThemeContextInjector
91 | ;
92 | ```
93 |
94 | ### Caveats
95 |
96 | The polyfilled `forwardRef` is only compatible with refs created from `createRef` and not compatible with `ref` callbacks/functions. If you attach a ref callback to a component returned from the polyfilled `forwardRef`, you will get a RefForwarder component instance. This is one instance of how this library differs from React's implementation. React actually built an internal type to handle this, which cannot be polyfilled, and returns the actual forwared child. However, this polyfill provides a `getRef` function you can use to make sure the correct ref is always returned (polyfilled or not).
97 |
98 | ## Extra APIs not in React
99 |
100 | ### getRef(ref)
101 |
102 | Arguments
103 |
104 | * [`ref`: `Node | Instance | null`]: Use this function to get the actual ref from a ref object created by `createRef` or `React.createRef`.
105 |
106 | Example:
107 |
108 | Using with `createRef`
109 |
110 | ```javascript
111 | class {
112 | divRef = createRef();
113 |
114 | componentDidMount() {
115 | // When using React.createRef or polyfilled createRef,
116 | // to get the actual div dom node, you have to access
117 | // it on the `current` property.
118 | // For example, this.divRef.current === getRef(this.divRef);
119 | const node = getRef(this.divRef); // returns div node
120 | }
121 | render() {
122 | return