From 966565956a1634006f0a924ce7078990036737a4 Mon Sep 17 00:00:00 2001 From: Michael Jackson Date: Tue, 17 Sep 2019 12:08:40 -0700 Subject: [PATCH] Fix element This commit fixes so that they do not render if the route does not match and they are elements. functions still work as they did previously. Fixes #6362 --- packages/react-router/modules/Route.js | 60 ++++---- .../modules/__tests__/Route-test.js | 144 ++++++++++++++---- 2 files changed, 148 insertions(+), 56 deletions(-) diff --git a/packages/react-router/modules/Route.js b/packages/react-router/modules/Route.js index e4624ff47e..43af9a197a 100644 --- a/packages/react-router/modules/Route.js +++ b/packages/react-router/modules/Route.js @@ -11,6 +11,19 @@ function isEmptyChildren(children) { return React.Children.count(children) === 0; } +function evalChildrenDev(children, props, path) { + const value = children(props); + + warning( + value !== undefined, + "You returned `undefined` from the `children` function of " + + `, but you ` + + "should have returned a React element or `null`" + ); + + return value || null; +} + /** * The public API for matching a single path and rendering. */ @@ -25,8 +38,8 @@ class Route extends React.Component { const match = this.props.computedMatch ? this.props.computedMatch // already computed the match for us : this.props.path - ? matchPath(location.pathname, this.props) - : context.match; + ? matchPath(location.pathname, this.props) + : context.match; const props = { ...context, location, match }; @@ -38,36 +51,25 @@ class Route extends React.Component { children = null; } - if (typeof children === "function") { - children = children(props); - - if (children === undefined) { - if (__DEV__) { - const { path } = this.props; - - warning( - false, - "You returned `undefined` from the `children` function of " + - `, but you ` + - "should have returned a React element or `null`" - ); - } - - children = null; - } - } - return ( - {children && !isEmptyChildren(children) + {props.match ? children - : props.match - ? component - ? React.createElement(component, props) - : render - ? render(props) - : null - : null} + ? typeof children === "function" + ? __DEV__ + ? evalChildrenDev(children, props, this.props.path) + : children(props) + : children + : component + ? React.createElement(component, props) + : render + ? render(props) + : null + : typeof children === "function" + ? __DEV__ + ? evalChildrenDev(children, props, this.props.path) + : children(props) + : null} ); }} diff --git a/packages/react-router/modules/__tests__/Route-test.js b/packages/react-router/modules/__tests__/Route-test.js index 5b59dc17f1..fe6afb4636 100644 --- a/packages/react-router/modules/__tests__/Route-test.js +++ b/packages/react-router/modules/__tests__/Route-test.js @@ -22,43 +22,133 @@ describe("A ", () => { }); }); - it("renders when it matches", () => { - const text = "cupcakes"; + describe("with a child element", () => { + it("renders when it matches", () => { + const text = "cupcakes"; - renderStrict( - -

{text}

} /> -
, - node - ); + renderStrict( + + +

{text}

+
+
, + node + ); + + expect(node.innerHTML).toContain(text); + }); + + it("renders when it matches at the root URL", () => { + const text = "cupcakes"; + + renderStrict( + + +

{text}

+
+
, + node + ); + + expect(node.innerHTML).toContain(text); + }); + + it("does not render when it does not match", () => { + const text = "bubblegum"; - expect(node.innerHTML).toContain(text); + renderStrict( + + +

{text}

+
+
, + node + ); + + expect(node.innerHTML).not.toContain(text); + }); }); - it("renders when it matches at the root URL", () => { - const text = "cupcakes"; + describe("with a children function", () => { + it("renders when it matches", () => { + const text = "cupcakes"; - renderStrict( - -

{text}

} /> -
, - node - ); + renderStrict( + +

{text}

} /> +
, + node + ); + + expect(node.innerHTML).toContain(text); + }); - expect(node.innerHTML).toContain(text); + it("renders when it matches at the root URL", () => { + const text = "cupcakes"; + + renderStrict( + +

{text}

} /> +
, + node + ); + + expect(node.innerHTML).toContain(text); + }); + + it("renders when it does not match", () => { + const text = "bubblegum"; + + renderStrict( + +

{text}

} /> +
, + node + ); + + expect(node.innerHTML).toContain(text); + }); }); - it("does not render when it does not match", () => { - const text = "bubblegum"; + describe("with a render prop", () => { + it("renders when it matches", () => { + const text = "cupcakes"; - renderStrict( - -

{text}

} /> -
, - node - ); + renderStrict( + +

{text}

} /> +
, + node + ); - expect(node.innerHTML).not.toContain(text); + expect(node.innerHTML).toContain(text); + }); + + it("renders when it matches at the root URL", () => { + const text = "cupcakes"; + + renderStrict( + +

{text}

} /> +
, + node + ); + + expect(node.innerHTML).toContain(text); + }); + + it("does not render when it does not match", () => { + const text = "bubblegum"; + + renderStrict( + +

{text}

} /> +
, + node + ); + + expect(node.innerHTML).not.toContain(text); + }); }); it("matches using nextContext when updating", () => {