diff --git a/modules/InternalPropTypes.js b/modules/InternalPropTypes.js index e541233c2e..194e70df12 100644 --- a/modules/InternalPropTypes.js +++ b/modules/InternalPropTypes.js @@ -1,4 +1,4 @@ -import { func, object, arrayOf, oneOfType, element, shape, string } from 'prop-types' +import { func, object, arrayOf, oneOfType, element, shape, elementType } from 'prop-types' export function falsy(props, propName, componentName) { if (props[propName]) @@ -14,7 +14,7 @@ export const history = shape({ goForward: func.isRequired }) -export const component = oneOfType([ func, string ]) +export const component = elementType export const components = oneOfType([ component, object ]) export const route = oneOfType([ object, element ]) export const routes = oneOfType([ route, arrayOf(route) ]) diff --git a/modules/RouterContext.js b/modules/RouterContext.js index e2aa5a8850..b872c5e734 100644 --- a/modules/RouterContext.js +++ b/modules/RouterContext.js @@ -1,5 +1,6 @@ import invariant from 'invariant' import React from 'react' +import { isValidElementType } from 'react-is' import createReactClass from 'create-react-class' import { array, func, object } from 'prop-types' @@ -73,7 +74,9 @@ const RouterContext = createReactClass({ props[prop] = element[prop] } - if (typeof components === 'object') { + // Handle components is object for { [name]: component } but not valid element + // type of react, such as React.memo, React.lazy and so on. + if (typeof components === 'object' && !isValidElementType(components)) { const elements = {} for (const key in components) { diff --git a/modules/__tests__/Router-test.js b/modules/__tests__/Router-test.js index c799093f50..6701897c24 100644 --- a/modules/__tests__/Router-test.js +++ b/modules/__tests__/Router-test.js @@ -1,5 +1,5 @@ import expect from 'expect' -import React, { Component } from 'react' +import React, { Component, Fragment, forwardRef, memo } from 'react' import { render, unmountComponentAtNode } from 'react-dom' import createHistory from '../createMemoryHistory' import Route from '../Route' @@ -104,6 +104,41 @@ describe('Router', function () { }) }) + describe('components for React 16', function () { + it('renders routes for React.memo', function (done) { + render(( + +
memo
)} /> +
+ ), node, function () { + expect(node.textContent).toEqual('memo') + done() + }) + }) + + it('renders routes for React.forwardRef', function (done) { + render(( + +
forwardRef
)} /> +
+ ), node, function () { + expect(node.textContent).toEqual('forwardRef') + done() + }) + }) + + it('renders routes for React.Fragment', function (done) { + render(( + +
Fragment
} /> +
+ ), node, function () { + expect(node.textContent).toEqual('Fragment') + done() + }) + }) + }) + describe('with named components', function () { class Parent extends Component { render() { diff --git a/package.json b/package.json index 4e1039d337..6d0a5b9f49 100644 --- a/package.json +++ b/package.json @@ -38,7 +38,8 @@ "hoist-non-react-statics": "^2.3.1", "invariant": "^2.2.1", "loose-envify": "^1.2.0", - "prop-types": "^15.5.6", + "prop-types": "^15.7.2", + "react-is": "^16.8.6", "warning": "^3.0.0" }, "peerDependencies": { @@ -79,9 +80,9 @@ "mocha": "^5.0.4", "pretty-bytes": "^4.0.2", "qs": "^6.2.1", - "react": "^16.0.0-rc", + "react": "^16.8.6", "react-addons-css-transition-group": "^15.6.0", - "react-dom": "^16.0.0-rc", + "react-dom": "^16.8.6", "rimraf": "^2.5.4", "style-loader": "^0.16.1", "webpack": "^1.13.1", diff --git a/yarn.lock b/yarn.lock index 760b23ae60..ec3aa4514d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3545,6 +3545,11 @@ js-tokens@^3.0.0, js-tokens@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b" +"js-tokens@^3.0.0 || ^4.0.0": + version "4.0.0" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" + integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== + js-yaml@3.x, js-yaml@^3.5.1: version "3.11.0" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.11.0.tgz#597c1a8bd57152f26d622ce4117851a51f5ebaef" @@ -3861,12 +3866,19 @@ longest@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/longest/-/longest-1.0.1.tgz#30a0b2da38f73770e8294a0d22e6625ed77d0097" -loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.2.0, loose-envify@^1.3.1: +loose-envify@^1.0.0, loose-envify@^1.2.0, loose-envify@^1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.3.1.tgz#d1a8ad33fa9ce0e713d65fdd0ac8b748d478c848" dependencies: js-tokens "^3.0.0" +loose-envify@^1.1.0, loose-envify@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" + integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== + dependencies: + js-tokens "^3.0.0 || ^4.0.0" + loud-rejection@^1.0.0: version "1.6.0" resolved "https://registry.yarnpkg.com/loud-rejection/-/loud-rejection-1.6.0.tgz#5b46f80147edee578870f086d04821cf998e551f" @@ -4886,7 +4898,7 @@ promise@^7.1.1: dependencies: asap "~2.0.3" -prop-types@^15.5.6, prop-types@^15.6.0: +prop-types@^15.5.6: version "15.6.1" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.6.1.tgz#36644453564255ddda391191fb3a125cbdf654ca" dependencies: @@ -4894,6 +4906,15 @@ prop-types@^15.5.6, prop-types@^15.6.0: loose-envify "^1.3.1" object-assign "^4.1.1" +prop-types@^15.6.2, prop-types@^15.7.2: + version "15.7.2" + resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.7.2.tgz#52c41e75b8c87e72b9d9360e0206b99dcbffa6c5" + integrity sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ== + dependencies: + loose-envify "^1.4.0" + object-assign "^4.1.1" + react-is "^16.8.1" + proxy-addr@~2.0.2: version "2.0.3" resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.3.tgz#355f262505a621646b3130a728eb647e22055341" @@ -5036,14 +5057,20 @@ react-addons-css-transition-group@^15.6.0: dependencies: react-transition-group "^1.2.0" -react-dom@^16.0.0-rc: - version "16.2.0" - resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.2.0.tgz#69003178601c0ca19b709b33a83369fe6124c044" +react-dom@^16.8.6: + version "16.8.6" + resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.8.6.tgz#71d6303f631e8b0097f56165ef608f051ff6e10f" + integrity sha512-1nL7PIq9LTL3fthPqwkvr2zY7phIPjYrT0jp4HjyEQrEROnw4dG41VVwi/wfoCneoleqrNX7iAD+pXebJZwrwA== 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.13.6" + +react-is@^16.8.1, react-is@^16.8.6: + version "16.8.6" + resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.8.6.tgz#5bbc1e2d29141c9fbdfed456343fe2bc430a6a16" + integrity sha512-aUk3bHfZ2bRSVFFbbeVS4i+lNPZr3/WM5jT2J5omUVV1zzcs1nAaf3l51ctA5FFvCRbhrH0bdAsRRQddFJZPtA== react-transition-group@^1.2.0: version "1.2.1" @@ -5055,14 +5082,15 @@ react-transition-group@^1.2.0: prop-types "^15.5.6" warning "^3.0.0" -react@^16.0.0-rc: - version "16.2.0" - resolved "https://registry.yarnpkg.com/react/-/react-16.2.0.tgz#a31bd2dab89bff65d42134fa187f24d054c273ba" +react@^16.8.6: + version "16.8.6" + resolved "https://registry.yarnpkg.com/react/-/react-16.8.6.tgz#ad6c3a9614fd3a4e9ef51117f54d888da01f2bbe" + integrity sha512-pC0uMkhLaHm11ZSJULfOBqV4tIZkx87ZLvbbQYunNixAAvjnC+snJCg0XQXn9VIsttVsbZP/H/ewzgsd5fxKXw== 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.13.6" read-only-stream@^2.0.0: version "2.0.0" @@ -5426,6 +5454,14 @@ sax@~1.2.1: version "1.2.4" resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" +scheduler@^0.13.6: + version "0.13.6" + resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.13.6.tgz#466a4ec332467b31a91b9bf74e5347072e4cd889" + integrity sha512-IWnObHt413ucAYKsD9J1QShUKkbKLQQHdxRyw73sw4FN26iWr3DY/H34xGPe4nmL1DwXyWmSWmMrA9TfQbE/XQ== + dependencies: + loose-envify "^1.1.0" + object-assign "^4.1.1" + "semver@2 || 3 || 4 || 5", semver@^5.3.0: version "5.5.0" resolved "https://registry.yarnpkg.com/semver/-/semver-5.5.0.tgz#dc4bbc7a6ca9d916dee5d43516f0092b58f7b8ab"