Skip to content

Commit 427db56

Browse files
committed
Use constructor instead of cWM in <Redirect>
1 parent 33c6f6f commit 427db56

File tree

4 files changed

+79
-76
lines changed

4 files changed

+79
-76
lines changed

packages/react-router/modules/Redirect.js

+4-11
Original file line numberDiff line numberDiff line change
@@ -23,29 +23,22 @@ function computeTo(props) {
2323
}
2424

2525
/**
26-
* The public API for updating the location programmatically
27-
* with a component.
26+
* The public API for updating the location programmatically with a component.
2827
*/
2928
class InnerRedirect extends React.Component {
3029
static defaultProps = {
3130
push: false
3231
};
3332

34-
isStatic() {
35-
return this.props.router && this.props.router.staticContext;
36-
}
33+
constructor(props) {
34+
super(props);
3735

38-
componentWillMount() {
3936
invariant(
4037
this.props.router,
4138
"You should not use <Redirect> outside a <Router>"
4239
);
4340

44-
if (this.isStatic()) this.perform();
45-
}
46-
47-
componentDidMount() {
48-
if (!this.isStatic()) this.perform();
41+
this.perform();
4942
}
5043

5144
componentDidUpdate(prevProps) {

packages/react-router/modules/Route.js

+26-26
Original file line numberDiff line numberDiff line change
@@ -46,12 +46,37 @@ class Route extends React.Component {
4646
};
4747

4848
getChildContext() {
49-
// TODO: Warn about accessing context directly. It will be removed.
49+
// TODO: Warn about accessing this.context.router directly. It will be removed.
5050
return {
5151
router: getContext(this.props, this.context.router)
5252
};
5353
}
5454

55+
constructor(props) {
56+
super(props);
57+
58+
if (__DEV__) {
59+
warning(
60+
!(props.component && props.render),
61+
"You should not use <Route component> and <Route render> in the same route; <Route render> will be ignored"
62+
);
63+
64+
warning(
65+
!(
66+
props.component &&
67+
props.children &&
68+
!isEmptyChildren(props.children)
69+
),
70+
"You should not use <Route component> and <Route children> in the same route; <Route children> will be ignored"
71+
);
72+
73+
warning(
74+
!(props.render && props.children && !isEmptyChildren(props.children)),
75+
"You should not use <Route render> and <Route children> in the same route; <Route children> will be ignored"
76+
);
77+
}
78+
}
79+
5580
render() {
5681
return (
5782
<RouterContext.Consumer>
@@ -107,31 +132,6 @@ if (__DEV__) {
107132
location: PropTypes.object
108133
};
109134

110-
Route.prototype.componentDidMount = function() {
111-
warning(
112-
!(this.props.component && this.props.render),
113-
"You should not use <Route component> and <Route render> in the same route; <Route render> will be ignored"
114-
);
115-
116-
warning(
117-
!(
118-
this.props.component &&
119-
this.props.children &&
120-
!isEmptyChildren(this.props.children)
121-
),
122-
"You should not use <Route component> and <Route children> in the same route; <Route children> will be ignored"
123-
);
124-
125-
warning(
126-
!(
127-
this.props.render &&
128-
this.props.children &&
129-
!isEmptyChildren(this.props.children)
130-
),
131-
"You should not use <Route render> and <Route children> in the same route; <Route children> will be ignored"
132-
);
133-
};
134-
135135
Route.prototype.componentDidUpdate = function(prevProps) {
136136
warning(
137137
!(this.props.location && !prevProps.location),

packages/react-router/modules/Router.js

+12-12
Original file line numberDiff line numberDiff line change
@@ -28,21 +28,20 @@ class Router extends React.Component {
2828
};
2929

3030
getChildContext() {
31-
// TODO: Warn about accessing context directly. It will be removed.
31+
// TODO: Warn about accessing this.context.router directly. It will be removed.
3232
return {
3333
router: getContext(this.props, this.state)
3434
};
3535
}
3636

37-
state = {
38-
location: this.props.history.location
39-
};
37+
constructor(props) {
38+
super(props);
39+
40+
this.state = {
41+
location: props.history.location
42+
};
4043

41-
componentWillMount() {
42-
// Do this here so we can setState when a <Redirect> changes the
43-
// location in componentWillMount. This happens e.g. when doing
44-
// server rendering using a <StaticRouter>.
45-
this.unlisten = this.props.history.listen(location => {
44+
this.unlisten = props.history.listen(location => {
4645
this.setState({ location });
4746
});
4847
}
@@ -55,9 +54,10 @@ class Router extends React.Component {
5554
const context = getContext(this.props, this.state);
5655

5756
return (
58-
<RouterContext.Provider value={context}>
59-
{this.props.children || null}
60-
</RouterContext.Provider>
57+
<RouterContext.Provider
58+
children={this.props.children || null}
59+
value={context}
60+
/>
6161
);
6262
}
6363
}

packages/react-router/modules/__tests__/Switch-test.js

+37-27
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ describe("A <Switch>", () => {
1414
});
1515

1616
describe("without a <Router>", () => {
17-
it("throws", () => {
17+
it("throws an error", () => {
1818
spyOn(console, "error");
1919

2020
expect(() => {
@@ -34,80 +34,90 @@ describe("A <Switch>", () => {
3434
node
3535
);
3636

37-
expect(node.innerHTML).toMatch(/one/);
37+
expect(node.innerHTML).toContain("one");
3838
});
3939

40-
it("renders the first <Redirect from> that matches the URL", () => {
40+
it("does not render a second <Route> that also matches the URL", () => {
41+
ReactDOM.render(
42+
<MemoryRouter initialEntries={["/one"]}>
43+
<Switch>
44+
<Route path="/one" render={() => <h1>one</h1>} />
45+
<Route path="/one" render={() => <h1>two</h1>} />
46+
</Switch>
47+
</MemoryRouter>,
48+
node
49+
);
50+
51+
expect(node.innerHTML).not.toContain("two");
52+
});
53+
54+
it("renders the first <Redirect> that matches the URL", () => {
4155
ReactDOM.render(
4256
<MemoryRouter initialEntries={["/three"]}>
4357
<Switch>
4458
<Route path="/one" render={() => <h1>one</h1>} />
45-
<Redirect from="/four" to="/one" />
46-
<Redirect from="/three" to="/two" />
4759
<Route path="/two" render={() => <h1>two</h1>} />
60+
<Redirect from="/three" to="/two" />
4861
</Switch>
4962
</MemoryRouter>,
5063
node
5164
);
5265

53-
expect(node.innerHTML).toMatch(/two/);
66+
expect(node.innerHTML).toContain("two");
5467
});
5568

56-
it("does not render a second <Route> or <Redirect> that also matches the URL", () => {
69+
it("does not render a second <Redirect> that also matches the URL", () => {
5770
ReactDOM.render(
58-
<MemoryRouter initialEntries={["/one"]}>
71+
<MemoryRouter initialEntries={["/three"]}>
5972
<Switch>
6073
<Route path="/one" render={() => <h1>one</h1>} />
61-
<Redirect from="/one" to="/two" />
62-
<Route path="/one" render={() => <h1>two</h1>} />
6374
<Route path="/two" render={() => <h1>two</h1>} />
75+
<Redirect from="/three" to="/two" />
76+
<Redirect from="/three" to="/one" />
6477
</Switch>
6578
</MemoryRouter>,
6679
node
6780
);
6881

69-
expect(node.innerHTML).not.toMatch(/two/);
82+
expect(node.innerHTML).toContain("two");
7083
});
7184

72-
it("renders pathless Routes", () => {
85+
it("renders a Route with no `path` prop", () => {
7386
ReactDOM.render(
74-
<MemoryRouter initialEntries={["/cupcakes"]}>
87+
<MemoryRouter initialEntries={["/two"]}>
7588
<Switch>
76-
<Route path="/bubblegum" render={() => <div>one</div>} />
77-
<Route render={() => <div>two</div>} />
89+
<Route path="/one" render={() => <h1>one</h1>} />
90+
<Route render={() => <h1>two</h1>} />
7891
</Switch>
7992
</MemoryRouter>,
8093
node
8194
);
8295

83-
expect(node.innerHTML).not.toContain("one");
8496
expect(node.innerHTML).toContain("two");
8597
});
8698

87-
it("handles from-less Redirects", () => {
99+
it("renders a Redirect with no `from` prop", () => {
88100
ReactDOM.render(
89-
<MemoryRouter initialEntries={["/cupcakes"]}>
101+
<MemoryRouter initialEntries={["/three"]}>
90102
<Switch>
91-
<Route path="/bubblegum" render={() => <div>bub</div>} />
92-
<Redirect to="/bubblegum" />
93-
<Route path="/cupcakes" render={() => <div>cup</div>} />
103+
<Route path="/one" render={() => <h1>one</h1>} />
104+
<Redirect to="/one" />
105+
<Route path="/two" render={() => <h1>two</h1>} />
94106
</Switch>
95107
</MemoryRouter>,
96108
node
97109
);
98110

99-
expect(node.innerHTML).not.toContain("cup");
100-
expect(node.innerHTML).toContain("bub");
111+
expect(node.innerHTML).toContain("one");
101112
});
102113

103114
it("handles subsequent redirects", () => {
104115
ReactDOM.render(
105116
<MemoryRouter initialEntries={["/one"]}>
106117
<Switch>
107-
<Redirect exact from="/one" to="/two" />
108-
<Redirect exact from="/two" to="/three" />
109-
110-
<Route path="/three" render={() => <div>three</div>} />
118+
<Redirect from="/one" to="/two" />
119+
<Redirect from="/two" to="/three" />
120+
<Route path="/three" render={() => <h1>three</h1>} />
111121
</Switch>
112122
</MemoryRouter>,
113123
node

0 commit comments

Comments
 (0)