diff --git a/src/components/ErrorDecoder/ErrorDecoder.js b/src/components/ErrorDecoder/ErrorDecoder.js index 3e638d61..51f2d8c3 100644 --- a/src/components/ErrorDecoder/ErrorDecoder.js +++ b/src/components/ErrorDecoder/ErrorDecoder.js @@ -2,14 +2,16 @@ * 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'; -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,27 +19,31 @@ 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); +// `?invariant=123&args[]=foo&args[]=bar` +// or `// ?invariant=123&args[0]=foo&args[1]=bar` +function parseQueryString( + search: string, +): ?{|code: string, args: Array|} { + const rawQueryString = search.substring(1); if (!rawQueryString) { return null; } @@ -50,15 +56,15 @@ function parseQueryString(location) { 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)); + } else if (query.indexOf('args[') === 0) { + args.push(query.slice(query.indexOf(']=') + 2)); } } - return [code, args]; + return {args, code}; } -function ErrorResult(props) { +function ErrorResult(props: {|code: ?string, msg: string|}) { const code = props.code; const errorMsg = props.msg; @@ -79,39 +85,21 @@ function ErrorResult(props) { ); } -class ErrorDecoder extends Component { - constructor(...args) { - super(...args); - - this.state = { - code: null, - errorMsg: '', - }; +function ErrorDecoder(props: {| + errorCodesString: string, + location: {search: string}, +|}) { + let code = null; + let msg = ''; + + 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;