From d73bff098221a9d854f11708b8471bea432670e3 Mon Sep 17 00:00:00 2001 From: Keyan Zhang Date: Tue, 31 Oct 2017 23:26:08 -0700 Subject: [PATCH 1/3] Use qs to parse query params --- flow-typed/qs.js | 5 ++ package.json | 1 + src/components/ErrorDecoder/ErrorDecoder.js | 98 ++++++++------------- yarn.lock | 4 + 4 files changed, 47 insertions(+), 61 deletions(-) create mode 100644 flow-typed/qs.js diff --git a/flow-typed/qs.js b/flow-typed/qs.js new file mode 100644 index 000000000..bd7c49936 --- /dev/null +++ b/flow-typed/qs.js @@ -0,0 +1,5 @@ +declare module 'qs' { + declare module.exports: { + parse: (str: string, opts: Object) => Object; + }; +} diff --git a/package.json b/package.json index dbb60bb28..9752705ea 100644 --- a/package.json +++ b/package.json @@ -50,6 +50,7 @@ "glamor": "^2.20.40", "hex2rgba": "^0.0.1", "prettier": "^1.7.4", + "qs": "^6.5.1", "remarkable": "^1.7.1", "request-promise": "^4.2.2", "rimraf": "^2.6.1", diff --git a/src/components/ErrorDecoder/ErrorDecoder.js b/src/components/ErrorDecoder/ErrorDecoder.js index 3e638d617..c41a774e5 100644 --- a/src/components/ErrorDecoder/ErrorDecoder.js +++ b/src/components/ErrorDecoder/ErrorDecoder.js @@ -2,14 +2,17 @@ * Copyright (c) 2013-present, Facebook, Inc. * * @emails react-core + * @flow */ 'use strict'; -import React, {Component} from 'react'; -import PropTypes from 'prop-types'; +import React from 'react'; +import qs from 'qs'; -function replaceArgs(msg, argList) { +import type {Node} from 'react'; + +function replaceArgs(msg: string, argList: Array): string { let argIdx = 0; return msg.replace(/%s/g, function() { const arg = argList[argIdx++]; @@ -17,48 +20,39 @@ function replaceArgs(msg, argList) { }); } -function urlify(str) { +// When the message contains a URL (like https://fb.me/react-refs-must-have-owner), +// make it a clickable link. +function urlify(str: string): Node { const urlRegex = /(https:\/\/fb\.me\/[a-z\-]+)/g; const segments = str.split(urlRegex); - for (let i = 0; i < segments.length; i++) { + return segments.map((message, i) => { if (i % 2 === 1) { - segments[i] = ( - - {segments[i]} + return ( + + {message} ); } - } - - return segments; + return message; + }); } -// ?invariant=123&args[]=foo&args[]=bar -function parseQueryString(location) { - const rawQueryString = location.search.substring(1); - if (!rawQueryString) { +// `?invariant=123&args[]=foo&args[]=bar` +// or `// ?invariant=123&args[0]=foo&args[1]=bar` +function parseQueryString(search: string): ?{code: string, args: Array} { + const qsResult = qs.parse(search, {ignoreQueryPrefix: true}); + if (!qsResult.invariant) { return null; } - - let code = ''; - let args = []; - - const queries = rawQueryString.split('&'); - for (let i = 0; i < queries.length; i++) { - const query = decodeURIComponent(queries[i]); - if (query.indexOf('invariant=') === 0) { - code = query.slice(10); - } else if (query.indexOf('args[]=') === 0) { - args.push(query.slice(7)); - } - } - - return [code, args]; + return { + code: qsResult.invariant, + args: qsResult.args || [], + }; } -function ErrorResult(props) { +function ErrorResult(props: {code: ?string, msg: string}) { const code = props.code; const errorMsg = props.msg; @@ -79,39 +73,21 @@ function ErrorResult(props) { ); } -class ErrorDecoder extends Component { - constructor(...args) { - super(...args); +function ErrorDecoder(props: {| + errorCodesString: string, + location: {search: string}, +|}) { + let code = null; + let msg = ''; - this.state = { - code: null, - errorMsg: '', - }; + const errorCodes = JSON.parse(props.errorCodesString); + const parseResult = parseQueryString(props.location.search); + if (parseResult != null) { + code = parseResult.code; + msg = replaceArgs(errorCodes[code], parseResult.args); } - componentWillMount() { - const {errorCodesString} = this.props; - const errorCodes = JSON.parse(errorCodesString); - const parseResult = parseQueryString(this.props.location); - if (parseResult != null) { - const [code, args] = parseResult; - if (errorCodes[code]) { - this.setState({ - code: code, - errorMsg: replaceArgs(errorCodes[code], args), - }); - } - } - } - - render() { - return ; - } + return ; } -ErrorDecoder.propTypes = { - errorCodesString: PropTypes.string.isRequired, - location: PropTypes.object.isRequired, -}; - export default ErrorDecoder; diff --git a/yarn.lock b/yarn.lock index 826da4454..15973cef5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7688,6 +7688,10 @@ qs@6.4.0, qs@~6.4.0: version "6.4.0" resolved "https://registry.yarnpkg.com/qs/-/qs-6.4.0.tgz#13e26d28ad6b0ffaa91312cd3bf708ed351e7233" +qs@^6.5.1: + version "6.5.1" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.1.tgz#349cdf6eef89ec45c12d7d5eb3fc0c870343a6d8" + query-string@^4.1.0: version "4.3.4" resolved "https://registry.yarnpkg.com/query-string/-/query-string-4.3.4.tgz#bbb693b9ca915c232515b228b1a02b609043dbeb" From 5cc60281b531de7b6edc857f213a9d57bf69c517 Mon Sep 17 00:00:00 2001 From: Keyan Zhang Date: Tue, 31 Oct 2017 23:47:15 -0700 Subject: [PATCH 2/3] prettier --- flow-typed/qs.js | 2 +- src/components/ErrorDecoder/ErrorDecoder.js | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/flow-typed/qs.js b/flow-typed/qs.js index bd7c49936..eb06ded23 100644 --- a/flow-typed/qs.js +++ b/flow-typed/qs.js @@ -1,5 +1,5 @@ declare module 'qs' { declare module.exports: { - parse: (str: string, opts: Object) => Object; + parse: (str: string, opts: Object) => Object, }; } diff --git a/src/components/ErrorDecoder/ErrorDecoder.js b/src/components/ErrorDecoder/ErrorDecoder.js index c41a774e5..a53cfbe93 100644 --- a/src/components/ErrorDecoder/ErrorDecoder.js +++ b/src/components/ErrorDecoder/ErrorDecoder.js @@ -41,7 +41,9 @@ function urlify(str: string): Node { // `?invariant=123&args[]=foo&args[]=bar` // or `// ?invariant=123&args[0]=foo&args[1]=bar` -function parseQueryString(search: string): ?{code: string, args: Array} { +function parseQueryString( + search: string, +): ?{|code: string, args: Array|} { const qsResult = qs.parse(search, {ignoreQueryPrefix: true}); if (!qsResult.invariant) { return null; @@ -52,7 +54,7 @@ function parseQueryString(search: string): ?{code: string, args: Array} }; } -function ErrorResult(props: {code: ?string, msg: string}) { +function ErrorResult(props: {|code: ?string, msg: string|}) { const code = props.code; const errorMsg = props.msg; From d23c8c9aad317f4aa6aae072ff33be246885f7ac Mon Sep 17 00:00:00 2001 From: Brian Vaughn Date: Mon, 6 Nov 2017 14:59:38 +0000 Subject: [PATCH 3/3] Removed 'qs' module dependency from ErrorDecoder --- flow-typed/qs.js | 5 ----- package.json | 1 - src/components/ErrorDecoder/ErrorDecoder.js | 24 +++++++++++++++------ yarn.lock | 4 ---- 4 files changed, 17 insertions(+), 17 deletions(-) delete mode 100644 flow-typed/qs.js diff --git a/flow-typed/qs.js b/flow-typed/qs.js deleted file mode 100644 index eb06ded23..000000000 --- a/flow-typed/qs.js +++ /dev/null @@ -1,5 +0,0 @@ -declare module 'qs' { - declare module.exports: { - parse: (str: string, opts: Object) => Object, - }; -} diff --git a/package.json b/package.json index 9752705ea..dbb60bb28 100644 --- a/package.json +++ b/package.json @@ -50,7 +50,6 @@ "glamor": "^2.20.40", "hex2rgba": "^0.0.1", "prettier": "^1.7.4", - "qs": "^6.5.1", "remarkable": "^1.7.1", "request-promise": "^4.2.2", "rimraf": "^2.6.1", diff --git a/src/components/ErrorDecoder/ErrorDecoder.js b/src/components/ErrorDecoder/ErrorDecoder.js index a53cfbe93..51f2d8c39 100644 --- a/src/components/ErrorDecoder/ErrorDecoder.js +++ b/src/components/ErrorDecoder/ErrorDecoder.js @@ -8,7 +8,6 @@ 'use strict'; import React from 'react'; -import qs from 'qs'; import type {Node} from 'react'; @@ -44,14 +43,25 @@ function urlify(str: string): Node { function parseQueryString( search: string, ): ?{|code: string, args: Array|} { - const qsResult = qs.parse(search, {ignoreQueryPrefix: true}); - if (!qsResult.invariant) { + const rawQueryString = search.substring(1); + if (!rawQueryString) { return null; } - return { - code: qsResult.invariant, - args: qsResult.args || [], - }; + + let code = ''; + let args = []; + + const queries = rawQueryString.split('&'); + for (let i = 0; i < queries.length; i++) { + const query = decodeURIComponent(queries[i]); + if (query.indexOf('invariant=') === 0) { + code = query.slice(10); + } else if (query.indexOf('args[') === 0) { + args.push(query.slice(query.indexOf(']=') + 2)); + } + } + + return {args, code}; } function ErrorResult(props: {|code: ?string, msg: string|}) { diff --git a/yarn.lock b/yarn.lock index 15973cef5..826da4454 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7688,10 +7688,6 @@ qs@6.4.0, qs@~6.4.0: version "6.4.0" resolved "https://registry.yarnpkg.com/qs/-/qs-6.4.0.tgz#13e26d28ad6b0ffaa91312cd3bf708ed351e7233" -qs@^6.5.1: - version "6.5.1" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.1.tgz#349cdf6eef89ec45c12d7d5eb3fc0c870343a6d8" - query-string@^4.1.0: version "4.3.4" resolved "https://registry.yarnpkg.com/query-string/-/query-string-4.3.4.tgz#bbb693b9ca915c232515b228b1a02b609043dbeb"