2
2
* Copyright (c) 2013-present, Facebook, Inc.
3
3
*
4
4
* @emails react-core
5
+ * @flow
5
6
*/
6
7
7
8
'use strict' ;
8
9
9
- import React , { Component } from 'react' ;
10
- import PropTypes from 'prop-types ' ;
10
+ import React from 'react' ;
11
+ import qs from 'qs ' ;
11
12
12
- function replaceArgs ( msg , argList ) {
13
+ import type { Node } from 'react' ;
14
+
15
+ function replaceArgs ( msg : string , argList : Array < string > ) : string {
13
16
let argIdx = 0 ;
14
17
return msg . replace ( / % s / g, function ( ) {
15
18
const arg = argList [ argIdx ++ ] ;
16
19
return arg === undefined ? '[missing argument]' : arg ;
17
20
} ) ;
18
21
}
19
22
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 {
21
26
const urlRegex = / ( h t t p s : \/ \/ f b \. m e \/ [ a - z \- ] + ) / g;
22
27
23
28
const segments = str . split ( urlRegex ) ;
24
29
25
- for ( let i = 0 ; i < segments . length ; i ++ ) {
30
+ return segments . map ( ( message , i ) => {
26
31
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 }
30
35
</ a >
31
36
) ;
32
37
}
33
- }
34
-
35
- return segments ;
38
+ return message ;
39
+ } ) ;
36
40
}
37
41
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 ) {
42
47
return null ;
43
48
}
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
+ } ;
59
53
}
60
54
61
- function ErrorResult ( props ) {
55
+ function ErrorResult ( props : { code : ? string , msg : string } ) {
62
56
const code = props . code ;
63
57
const errorMsg = props . msg ;
64
58
@@ -79,39 +73,21 @@ function ErrorResult(props) {
79
73
) ;
80
74
}
81
75
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 ) ;
90
88
}
91
89
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} / > ;
110
91
}
111
92
112
- ErrorDecoder . propTypes = {
113
- errorCodesString : PropTypes . string . isRequired ,
114
- location : PropTypes . object . isRequired ,
115
- } ;
116
-
117
93
export default ErrorDecoder ;
0 commit comments