├── .prettierrc ├── reacts ├── 15.6 │ ├── package.json │ └── index.js ├── 16.2 │ ├── package.json │ └── index.js ├── 15.5 │ ├── package.json │ └── index.js ├── 16.0 │ ├── package.json │ └── index.js ├── 16.1 │ ├── package.json │ └── index.js ├── 0.14.9 │ ├── package.json │ └── index.js ├── 16.3 │ ├── package.json │ └── index.js ├── 15.0 │ ├── package.json │ └── index.js ├── 15.1 │ ├── package.json │ └── index.js ├── 15.2 │ ├── package.json │ └── index.js ├── 15.3 │ ├── package.json │ └── index.js └── 15.4 │ ├── package.json │ └── index.js ├── initTests.js ├── src ├── index.js ├── createRef.js ├── forwardRef.js ├── RefForwarder.js ├── getRef.js └── __tests__ │ ├── getRef.test.js │ ├── createRef.test.js │ └── forwardRef.test.js ├── .babelrc ├── test-utils ├── withReact.js └── installReactVersions.js ├── LICENSE ├── .gitignore ├── package.json └── README.md /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true 3 | } -------------------------------------------------------------------------------- /reacts/15.6/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "devDependencies": { 4 | "react": "15.6", 5 | "react-dom": "15.6" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /reacts/16.2/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "devDependencies": { 4 | "react": "16.2", 5 | "react-dom": "16.2" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /reacts/15.5/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "devDependencies": { 4 | "react": "^15.5.4", 5 | "react-dom": "^15.5.4" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /reacts/16.0/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "devDependencies": { 4 | "react": "^16.0.0", 5 | "react-dom": "^16.0.0" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /reacts/16.1/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "devDependencies": { 4 | "react": "^16.1.1", 5 | "react-dom": "^16.1.1" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /reacts/0.14.9/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "devDependencies": { 4 | "react": "^0.14.9", 5 | "react-dom": "^0.14.9" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /initTests.js: -------------------------------------------------------------------------------- 1 | const installReact = require('./test-utils/installReactVersions'); 2 | const path = require('path'); 3 | 4 | installReact(path.resolve('./reacts')); 5 | -------------------------------------------------------------------------------- /reacts/16.3/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "devDependencies": { 4 | "react": "^16.3.0-alpha.3", 5 | "react-dom": "^16.3.0-alpha.3" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | export { default as createRef } from './createRef'; 2 | export { default as forwardRef } from './forwardRef'; 3 | export { default as getRef } from './getRef'; 4 | -------------------------------------------------------------------------------- /reacts/15.0/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "devDependencies": { 4 | "react": "^15.0.2", 5 | "react-addons-test-utils": "^15.0.2", 6 | "react-dom": "^15.0.2" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /reacts/15.1/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "devDependencies": { 4 | "react": "^15.1.0", 5 | "react-addons-test-utils": "^15.1.0", 6 | "react-dom": "^15.1.0" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /reacts/15.2/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "devDependencies": { 4 | "react": "^15.2.1", 5 | "react-addons-test-utils": "^15.2.1", 6 | "react-dom": "^15.2.1" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /reacts/15.3/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "devDependencies": { 4 | "react": "^15.3.2", 5 | "react-addons-test-utils": "^15.3.2", 6 | "react-dom": "^15.3.2" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /reacts/15.4/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "devDependencies": { 4 | "react": "^15.4.2", 5 | "react-addons-test-utils": "^15.4.2", 6 | "react-dom": "^15.4.2" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /reacts/0.14.9/index.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | React: require('react'), 3 | ReactDOM: require('react-dom'), 4 | ReactDOMServer: require('react-dom/server'), 5 | TestUtils: require('react-dom/test-utils') 6 | }; 7 | -------------------------------------------------------------------------------- /reacts/15.0/index.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | React: require('react'), 3 | ReactDOM: require('react-dom'), 4 | ReactDOMServer: require('react-dom/server'), 5 | TestUtils: require('react-addons-test-utils') 6 | }; 7 | -------------------------------------------------------------------------------- /reacts/15.1/index.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | React: require('react'), 3 | ReactDOM: require('react-dom'), 4 | ReactDOMServer: require('react-dom/server'), 5 | TestUtils: require('react-addons-test-utils') 6 | }; 7 | -------------------------------------------------------------------------------- /reacts/15.2/index.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | React: require('react'), 3 | ReactDOM: require('react-dom'), 4 | ReactDOMServer: require('react-dom/server'), 5 | TestUtils: require('react-addons-test-utils') 6 | }; 7 | -------------------------------------------------------------------------------- /reacts/15.3/index.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | React: require('react'), 3 | ReactDOM: require('react-dom'), 4 | ReactDOMServer: require('react-dom/server'), 5 | TestUtils: require('react-addons-test-utils') 6 | }; 7 | -------------------------------------------------------------------------------- /reacts/15.4/index.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | React: require('react'), 3 | ReactDOM: require('react-dom'), 4 | ReactDOMServer: require('react-dom/server'), 5 | TestUtils: require('react-addons-test-utils') 6 | }; 7 | -------------------------------------------------------------------------------- /reacts/15.5/index.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | React: require('react'), 3 | ReactDOM: require('react-dom'), 4 | ReactDOMServer: require('react-dom/server'), 5 | TestUtils: require('react-dom/test-utils') 6 | }; 7 | -------------------------------------------------------------------------------- /reacts/15.6/index.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | React: require('react'), 3 | ReactDOM: require('react-dom'), 4 | ReactDOMServer: require('react-dom/server'), 5 | TestUtils: require('react-dom/test-utils') 6 | }; 7 | -------------------------------------------------------------------------------- /reacts/16.0/index.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | React: require('react'), 3 | ReactDOM: require('react-dom'), 4 | ReactDOMServer: require('react-dom/server'), 5 | TestUtils: require('react-dom/test-utils') 6 | }; 7 | -------------------------------------------------------------------------------- /reacts/16.1/index.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | React: require('react'), 3 | ReactDOM: require('react-dom'), 4 | ReactDOMServer: require('react-dom/server'), 5 | TestUtils: require('react-dom/test-utils') 6 | }; 7 | -------------------------------------------------------------------------------- /reacts/16.2/index.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | React: require('react'), 3 | ReactDOM: require('react-dom'), 4 | ReactDOMServer: require('react-dom/server'), 5 | TestUtils: require('react-dom/test-utils') 6 | }; 7 | -------------------------------------------------------------------------------- /reacts/16.3/index.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | React: require('react'), 3 | ReactDOM: require('react-dom'), 4 | ReactDOMServer: require('react-dom/server'), 5 | TestUtils: require('react-dom/test-utils') 6 | }; 7 | -------------------------------------------------------------------------------- /src/createRef.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import getRef from './getRef'; 3 | 4 | export default React.createRef || 5 | function createRef() { 6 | function ref(instanceOrNode) { 7 | ref.current = getRef(instanceOrNode) || null; 8 | } 9 | 10 | ref.current = null; 11 | 12 | if (process.env.NODE_ENV !== 'production') { 13 | Object.seal(ref); 14 | } 15 | 16 | return ref; 17 | }; 18 | -------------------------------------------------------------------------------- /.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 | } -------------------------------------------------------------------------------- /test-utils/withReact.js: -------------------------------------------------------------------------------- 1 | const { join } = require('path'); 2 | const { readdirSync } = require('fs'); 3 | const reacts = {}; 4 | 5 | require('raf/polyfill'); 6 | 7 | const reactsPath = join(__dirname, '../reacts'); 8 | readdirSync(reactsPath).forEach(version => { 9 | const cwd = join(reactsPath, version); 10 | reacts[version] = { 11 | ...require(cwd), 12 | version 13 | }; 14 | }); 15 | 16 | module.exports = function withReact(fn) { 17 | Object.keys(reacts).forEach(version => { 18 | fn(reacts[version]); 19 | }); 20 | }; 21 | -------------------------------------------------------------------------------- /src/forwardRef.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import createRef from './createRef'; 3 | import RefForwarder from './RefForwarder'; 4 | import warning from 'fbjs/lib/warning'; 5 | 6 | export default React.forwardRef || 7 | function forwardRef(render) { 8 | if (process.env.NODE_ENV !== 'production') { 9 | warning( 10 | typeof render === 'function', 11 | 'forwardRef requires a render function but was given %s.', 12 | render === null ? 'null' : typeof render 13 | ); 14 | } 15 | return class extends RefForwarder { 16 | __render = render; 17 | }; 18 | }; 19 | -------------------------------------------------------------------------------- /src/RefForwarder.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import createRef from './createRef'; 3 | 4 | export default class ForwardRefPolyfill extends React.Component { 5 | static displayName = 'ForwardRefPolyfill'; 6 | 7 | constructor(props) { 8 | super(props); 9 | this.__forwardedRef = createRef(); 10 | } 11 | 12 | __render() { 13 | return null; 14 | } 15 | 16 | getRef() { 17 | // Check for `.current` first before `.value` since it's the 18 | // newest property name in React. 19 | return this.__forwardedRef.current || this.__forwardedRef.value; 20 | } 21 | 22 | render() { 23 | return this.__render(this.props, this.__forwardedRef); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /test-utils/installReactVersions.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const { readdirSync } = require('fs'); 4 | const { join } = require('path'); 5 | const { spawnSync } = require('child_process'); 6 | const fs = require('fs'); 7 | 8 | module.exports = function(path) { 9 | return readdirSync(path).forEach(version => { 10 | const cwd = join(path, version); 11 | 12 | // try { 13 | // fs.statSync(join(cwd, 'node_modules')); 14 | // } catch(ex) { 15 | console.info(`Installing React version ${version} ...`); 16 | const spawn = spawnSync('npm', ['install'], { 17 | cwd, 18 | stdio: 'inherit' 19 | }); 20 | 21 | if (spawn.status > 0) { 22 | process.exit(spawn.status); 23 | } 24 | // } 25 | }); 26 | }; 27 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /.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 | -------------------------------------------------------------------------------- /src/getRef.js: -------------------------------------------------------------------------------- 1 | import { FORWARD_REF_KEY } from './forwardRef'; 2 | import RefForwarder from './RefForwarder'; 3 | import warning from 'fbjs/lib/warning'; 4 | 5 | export default function getRef(refObject) { 6 | if (!refObject) { 7 | return null; 8 | } 9 | 10 | let ref = refObject; 11 | 12 | if (typeof ref === 'function' && process.env.NODE_ENV !== 'production') { 13 | warning( 14 | ref.hasOwnProperty('current'), 15 | 'getRef: It looks like you may have passed `getRef` the ref callback as ' + 16 | 'an argument. `getRef` should be used with a ref object created by ' + 17 | '`createRef` or inside a ref callback.' 18 | ); 19 | } 20 | 21 | if (Object.keys(ref).length === 1) { 22 | if (ref.hasOwnProperty('current')) { 23 | ref = ref.current; 24 | // We probably don't have to support this route since it was only 25 | // in one version of React and it was an alpha release (16.3.0-alpha.1). 26 | } else if (ref.hasOwnProperty('value')) { 27 | ref = ref.value; 28 | } 29 | } 30 | 31 | // Get polyfilled forwardedRef, if it exists 32 | if (ref instanceof RefForwarder) { 33 | ref = ref.getRef(); 34 | } 35 | 36 | return ref; 37 | } 38 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "create-react-ref", 3 | "version": "0.1.0", 4 | "description": 5 | "Polyfill for the proposed React.createRef and React.forwardRef API", 6 | "main": "lib/index.js", 7 | "license": "MIT", 8 | "keywords": ["react", "polyfill", "ponyfill", "createRef", "forwardRef"], 9 | "repository": { 10 | "type": "git", 11 | "url": "https://github.com/soupaJ/create-react-ref.git" 12 | }, 13 | "files": ["lib"], 14 | "scripts": { 15 | "test": "node ./initTests.js && jest", 16 | "flow": "flow", 17 | "format": "prettier --write '**/*.{js,md,json,js.flow,d.ts}'", 18 | "build": "babel src -d lib --copy-files --ignore __tests__", 19 | "prepublish": "npm run build", 20 | "commit": "lint-staged" 21 | }, 22 | "peerDependencies": { 23 | "react": "^0.14.0 || ^15.0.0 || ^16.0.0" 24 | }, 25 | "devDependencies": { 26 | "babel-cli": "^6.26.0", 27 | "babel-plugin-add-module-exports": "^0.2.1", 28 | "babel-plugin-transform-class-properties": "^6.24.1", 29 | "babel-preset-env": "^1.6.1", 30 | "babel-preset-react": "^6.24.1", 31 | "husky": "^0.14.3", 32 | "jest": "^21.2.1", 33 | "lint-staged": "^6.0.0", 34 | "prettier": "^1.9.1", 35 | "prop-types": "^15.6.0", 36 | "raf": "^3.4.0", 37 | "react": "^16.2.0", 38 | "react-dom": "^16.2.0", 39 | "rollup": "^0.57.1" 40 | }, 41 | "lint-staged": { 42 | "*.{js,md,json,js.flow,d.ts}": ["prettier --write", "git add"] 43 | }, 44 | "jest": { 45 | "silent": true 46 | }, 47 | "dependencies": { 48 | "fbjs": "^0.8.16" 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/__tests__/getRef.test.js: -------------------------------------------------------------------------------- 1 | import withReact from '../../test-utils/withReact'; 2 | const name = 'cjs'; 3 | 4 | describe(`create-react-ref (${name})`, () => { 5 | withReact(({ React, ReactDOM, TestUtils, version }) => { 6 | describe(`react@${version}`, () => { 7 | let createRef; 8 | let forwardRef; 9 | let getRef; 10 | 11 | beforeEach(() => { 12 | jest.resetModules(); 13 | jest.setMock('react', React); 14 | jest.setMock('react-dom', ReactDOM); 15 | getRef = require('../getRef'); 16 | createRef = require('../createRef'); 17 | forwardRef = require('../forwardRef'); 18 | }); 19 | 20 | it('should do return the ref from the createRef object', () => { 21 | let ref = createRef(); 22 | const Component = props =>
; 23 | 24 | TestUtils.renderIntoDocument(