Skip to content

Commit d73bff0

Browse files
Keyan ZhangKeyan Zhang
Keyan Zhang
authored and
Keyan Zhang
committed
Use qs to parse query params
1 parent f456a7a commit d73bff0

File tree

4 files changed

+48
-62
lines changed

4 files changed

+48
-62
lines changed

flow-typed/qs.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
declare module 'qs' {
2+
declare module.exports: {
3+
parse: (str: string, opts: Object) => Object;
4+
};
5+
}

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@
5050
"glamor": "^2.20.40",
5151
"hex2rgba": "^0.0.1",
5252
"prettier": "^1.7.4",
53+
"qs": "^6.5.1",
5354
"remarkable": "^1.7.1",
5455
"request-promise": "^4.2.2",
5556
"rimraf": "^2.6.1",

src/components/ErrorDecoder/ErrorDecoder.js

Lines changed: 38 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -2,63 +2,57 @@
22
* Copyright (c) 2013-present, Facebook, Inc.
33
*
44
* @emails react-core
5+
* @flow
56
*/
67

78
'use strict';
89

9-
import React, {Component} from 'react';
10-
import PropTypes from 'prop-types';
10+
import React from 'react';
11+
import qs from 'qs';
1112

12-
function replaceArgs(msg, argList) {
13+
import type {Node} from 'react';
14+
15+
function replaceArgs(msg: string, argList: Array<string>): string {
1316
let argIdx = 0;
1417
return msg.replace(/%s/g, function() {
1518
const arg = argList[argIdx++];
1619
return arg === undefined ? '[missing argument]' : arg;
1720
});
1821
}
1922

20-
function urlify(str) {
23+
// When the message contains a URL (like https://fb.me/react-refs-must-have-owner),
24+
// make it a clickable link.
25+
function urlify(str: string): Node {
2126
const urlRegex = /(https:\/\/fb\.me\/[a-z\-]+)/g;
2227

2328
const segments = str.split(urlRegex);
2429

25-
for (let i = 0; i < segments.length; i++) {
30+
return segments.map((message, i) => {
2631
if (i % 2 === 1) {
27-
segments[i] = (
28-
<a key={i} target="_blank" rel="noopener" href={segments[i]}>
29-
{segments[i]}
32+
return (
33+
<a key={i} target="_blank" rel="noopener" href={message}>
34+
{message}
3035
</a>
3136
);
3237
}
33-
}
34-
35-
return segments;
38+
return message;
39+
});
3640
}
3741

38-
// ?invariant=123&args[]=foo&args[]=bar
39-
function parseQueryString(location) {
40-
const rawQueryString = location.search.substring(1);
41-
if (!rawQueryString) {
42+
// `?invariant=123&args[]=foo&args[]=bar`
43+
// or `// ?invariant=123&args[0]=foo&args[1]=bar`
44+
function parseQueryString(search: string): ?{code: string, args: Array<string>} {
45+
const qsResult = qs.parse(search, {ignoreQueryPrefix: true});
46+
if (!qsResult.invariant) {
4247
return null;
4348
}
44-
45-
let code = '';
46-
let args = [];
47-
48-
const queries = rawQueryString.split('&');
49-
for (let i = 0; i < queries.length; i++) {
50-
const query = decodeURIComponent(queries[i]);
51-
if (query.indexOf('invariant=') === 0) {
52-
code = query.slice(10);
53-
} else if (query.indexOf('args[]=') === 0) {
54-
args.push(query.slice(7));
55-
}
56-
}
57-
58-
return [code, args];
49+
return {
50+
code: qsResult.invariant,
51+
args: qsResult.args || [],
52+
};
5953
}
6054

61-
function ErrorResult(props) {
55+
function ErrorResult(props: {code: ?string, msg: string}) {
6256
const code = props.code;
6357
const errorMsg = props.msg;
6458

@@ -79,39 +73,21 @@ function ErrorResult(props) {
7973
);
8074
}
8175

82-
class ErrorDecoder extends Component {
83-
constructor(...args) {
84-
super(...args);
85-
86-
this.state = {
87-
code: null,
88-
errorMsg: '',
89-
};
76+
function ErrorDecoder(props: {|
77+
errorCodesString: string,
78+
location: {search: string},
79+
|}) {
80+
let code = null;
81+
let msg = '';
82+
83+
const errorCodes = JSON.parse(props.errorCodesString);
84+
const parseResult = parseQueryString(props.location.search);
85+
if (parseResult != null) {
86+
code = parseResult.code;
87+
msg = replaceArgs(errorCodes[code], parseResult.args);
9088
}
9189

92-
componentWillMount() {
93-
const {errorCodesString} = this.props;
94-
const errorCodes = JSON.parse(errorCodesString);
95-
const parseResult = parseQueryString(this.props.location);
96-
if (parseResult != null) {
97-
const [code, args] = parseResult;
98-
if (errorCodes[code]) {
99-
this.setState({
100-
code: code,
101-
errorMsg: replaceArgs(errorCodes[code], args),
102-
});
103-
}
104-
}
105-
}
106-
107-
render() {
108-
return <ErrorResult code={this.state.code} msg={this.state.errorMsg} />;
109-
}
90+
return <ErrorResult code={code} msg={msg} />;
11091
}
11192

112-
ErrorDecoder.propTypes = {
113-
errorCodesString: PropTypes.string.isRequired,
114-
location: PropTypes.object.isRequired,
115-
};
116-
11793
export default ErrorDecoder;

yarn.lock

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7688,6 +7688,10 @@ qs@6.4.0, qs@~6.4.0:
76887688
version "6.4.0"
76897689
resolved "https://registry.yarnpkg.com/qs/-/qs-6.4.0.tgz#13e26d28ad6b0ffaa91312cd3bf708ed351e7233"
76907690

7691+
qs@^6.5.1:
7692+
version "6.5.1"
7693+
resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.1.tgz#349cdf6eef89ec45c12d7d5eb3fc0c870343a6d8"
7694+
76917695
query-string@^4.1.0:
76927696
version "4.3.4"
76937697
resolved "https://registry.yarnpkg.com/query-string/-/query-string-4.3.4.tgz#bbb693b9ca915c232515b228b1a02b609043dbeb"

0 commit comments

Comments
 (0)