1 —— 组件名没有用大写字母开头


如果组件名不以大写字母开头,组件会被当作是内置元素,像是div 或 span


class greeting extends React.Component {   
  // ...  

如果你要渲染<greeting />,React会忽略上面内容,你也会收到警告:

Warning: The tag <greeting> is unrecognized in this browser. If you meant to render a React component, start its name with an uppercase letter.

这里更大的问题是当你决定命名你的button 或者 img组件时。React会忽略你的组件,并且只渲染原生的HTML button 或者 img标签。

注意上面的“My Awesome Button”并没有渲染,React只渲染了一个空的HTML button元素。这种情况下React不会警告你。

2 — Using single quotes instead of back-ticks


Strings created with back-ticks (`...` ) are different from strings created with single quotes ('...'). 用反撇号(`...` ) 创建的字符串和用单引号('...')创建的不一样。

On most keyboards, the back-tick (_`_) character can be typed using the key above the _tab_key. 在大部分键盘上,反撇号 (_`_)字符可以用 _tab_ 上的那个键输入。

We create a string using back-ticks when we need to include dynamic expressions inside that string (without resorting to string concatenation). 当我们需要在字符串里面包含动态表达式的时候(这样就不需要要字符串拼接),我们会创建一个反撇号的字符串。

**`**This is a string template literal that can include expressions**`**
**'**This is just a string, you cannot include expressions here**'**

Let’s say you want a string that always reports the current time: 一起看下如果需要一个不间断显示当前时间的字符串: “Time is ...”

// 当前时间字符串
const time = new Date().toLocaleTimeString();

// When using regular strings (single or double quotes),  
// 使用一般的字符串(单引或者双引号)时,
// you need to use string concatenation:  
'Time is ' + time

// When using back-ticks,  
// you can inject the time in the string using ${}  
`Time is ${time}`

Also, when using string literals (with back-ticks), you can create a string that spans multiple lines: 当然,在使用字符串时(使用反撇号),你可以创建一个分为多行的字符串:

const template = `I



Multiple Lines`;

You can’t do that with regular strings. 用普通字符串可做不到。

3— Using React.PropTypes


The PropTypes object was removed from React. It used to be available as React.PropTypes but you cannot use that anymore. PropTypes对象从React里移除了。其过去是以React.PropTypes的形式被使用,但是再也用不了了。

Instead, you need to: 相应的,你需要:

  1. Add the new prop-types package to your project: npm install prop-types
  2. 把新的prop-types包加到你的项目中:npm install prop-types
  3. Import it: import PropTypes from 'prop-types'
  4. 引入它:import PropTypes from 'prop-types'

Then you can use it. For example: PropTypes.string. 然后你就可以用它了。例如:PropTypes.string

If you incorrectly use React.PropTypes, you’ll get errors like: 如果你错误地使用了React.PropTypes,你会得到这样的错误提示:

TypeError: Cannot read property 'string' of undefined

4 — Not using the right versions of what a tutorial is using

4 ——不使用那些指南里面用的版本

When watching or reading content about coding and following up with the examples they present, make sure that you are using correct versions of the tools the content is using. Usually, using the latest version of each tool is a safe bet, but if the content is a bit old you might run into some deprecation issues. 当看或读代码的内容,以及使用指南里的例子时,确保你使用的是内容里工具的版本。通常,使用工具的最新版本是最安全的方式,但是如果内容过时的话,你可能会遇到一些弃用提醒。

To be safe, stick with the major versions for the used tools. For example, if the tutorial is using React 16, don’t follow up using React 15. 为了确保安全,使用相关工具的主干版本。例如,如果指南用的是React 16,不要去用React 15。

This is especially important for Node.js as well. You will face major problems if you use an older version of Node. For example, if you’re following along with some tutorial that uses Object.valuesand you are using Node 6.x, that method did not exist back then. You need Node 7.x or higher. 这点对于Node.js也很重要。如果使用旧版的Node,你会遇到一系列问题。例如,如果你正在看一些指南,这些指南使用了Object.values而你在用Node 6.x,那个版本此方法是不存在的。你需要Node 7.x或更高的版本。

5— Confusing functions with classes


Can you tell what's wrong with the following code? 你能看出来下面的代码出了什么问题吗? class Numbers extends React.Component {
const arrayOfNumbers = _.range(1, 10);

// ...

The code above is invalid because inside the body of a JavaScript class you don’t have the freedom of doing just about anything. You can only define methods and properties using limited syntax. 上面的代码之所以无效,是因为在JavaScript类体里你不可以乱写。你只能使用规定的语法定义方法和属性。

This is a bit confusing because the _{}_ used in the class syntax looks like the plain-old block scope, but it’s not. 这让人有点混乱因为类语法里的{}很像常见的块级作用域,但并不是。 Inside a function-based component, you DO have the freedom of doing just about anything: 在一个由函数构成的组件里,你就可以想怎么搞就怎么搞: // 这样完全没问题:

const Number = (props) => {
const arrayOfNumbers = _.range(1, 10);

// ...

6 — Passing numbers as strings

6 ——将数字作为字符串传递

You can pass a prop value with a string: 你可以用一个字符串传递属性值

<Greeting name="World" />

If you need to pass a numeric value, don’t use strings: 如果你需要传递数字类型的值,不要使用字符串: // 不要这么做

<Greeting counter="7" /> Instead, use curly braces to pass an actual numeric value: 取而代之,使用花括号传递实际数值: // 用这个替代 <Greeting counter={7} /> Using {7}, inside the Greetingcomponent, this.props.counter will have the actual numeric 7 value and it will be safe to do mathematical operations on that. If you pass it as “7” and then treat it as a number, you might run into unexpected results. 在 Greeting 组件里面使用{7}this.props.counter会被赋值7,并且对其进行数学运算也不会有问题。如果你传了“7”还把它当成数字,你可能会运行出意想不到的结果。 #### 7 — Forgetting that another app instance is still using the same port #### 7 ——忘记了另外一个app在用同样的端口 To run a web server, your need to use a host (like and a port (like 8080) to make the server listen for request on a valid http address. 为了运行web服务器,你需要使用host(像是127.0.0.1)和端口(像是8080)来让服务器监听有效http地址的请求。 Once the web server is running successfully, it has control over that port. You cannot use the same port for anything else. The port will be busy. 一旦成功运行,web服务器就占据了那个端口。你就不能让这个端口它用。端口会被占用。 If you try to run the same server in another terminal, you’ll get an error that the port is “in use”. Something like: 如果你再另外一个终端运行同样的服务器,你会得到一个端口被占用的错误提示。 像是这样: Error: listen EADDRINUSE Be aware that sometimes a web server might be running in the background or inside a detached screen/tmux session. You don’t see it, but it is still occupying the port. To restart your server, you need to “kill” the one that’s still running. 注意有时候web服务器会运行在 后台或者在分开的屏幕/tumux session。你看不见,但是它一直占据着端口。为了重启服务器,你需要“杀死”正在运行的那个。 To identify the process that’s using a certain port, you can either use a command like ps (and grep for something about your app) or if you know the port number you can use the lsof command: 为了鉴别正在使用特定端口的进程,你可以使用像ps ( grep 一些关于app的相关信息)的命令,或者如果知道端口号你也可以使用lsof命令: lsof -i :8080#### 8 — Forgetting to create environment variables #### 8 ——忘了创建环境变量 Some projects depend on the existence of shell environment variables in order to start. If you run these projects without the needed environment variables, they will try to use undefined values for them and will potentially give you some cryptic errors. 一些项目要依赖shell环境变量才能运行。如果你在没有所需环境变量的情况下运行这些项目,它们会用undefined的值,这样会给你带来潜在的未知错误。 For example, if a project connects to a database like MongoDB, chances are it uses an environment variable like process.env.MONGO_URI to connect to it. This allows the project to be used with different MongoDB instances in different environments. 例如,如果项目连到像MongoDB的数据库,有可能它使用了像process.env.MONGO_URI 的环境变量来连接。这就允许项目在不同的环境和不同的MongoDB实例一起使用。 To locally run the project that connects to a MongoDB, you have to export a MONGO_URIenvironment variable first. For example, if you have a local MongoDB running on port 27017, you would need to do this before running the project: 为了本地运行连接到MongoDB的项目,你必须先导出MONGO_URI的环境变量。例如,如果你有一个运行在端口27017的本地MongoDB,你需要在运行项目前做这些: export MONGO_URI = "mongodb://localhost:27017/mydb" You can grep the project source code for process.env to figure out what environment variables it needs in order to work correctly. 你可以grep项目源代码,找到process.env来查清楚其运行正常所需要的环境变量。 #### 9— Confusing curly braces {} with parentheses () #### 9——把花括号{}和圆括号()搞混 Instead of: 不要用: return {
}; You need: 这样用: return (
); The first one will try (and fail) to return an object while the second one will correctly call the something() function and return what that function returns. 第一段代码尝试(并且会失败)返回一个对象,然后第二段代码会正确地调用something()函数,并且返回函数返回的内容。 Since any <tag> in JSX will translate to a function call, this problem applies when returning any JSX. 由于JSX里的任何<tag>会被解析成函数调用,当返回任何JSX时这个问题也会出现。 This problem is also common in arrow functions’ short syntax. 这个问题在箭头函数的缩写语法中也很常见。 Instead of: 不要用: const Greeting = () => {

Hello World

}; You need: 这样用: const Greeting = () => (

Hello World

); When you use curly braces with an arrow function, you are starting the scope of that function. The short syntax of arrow functions does not use curly braces. 当你使用带有箭头函数的中括号时,你就新起了一个函数的作用域。箭头函数的缩写语法不用中括号。 #### 10 — Not wrapping objects with parentheses #### 10——不要用圆括号包裹对象 The curly braces vs. parentheses problem above is also confusing when you want to create a short arrow function that returns a plain-old object. 当你想创建一个返回普通对象的短箭头函数时,上面中括号和圆括号的问题同样会让人困扰。 Instead of: 不要用: const myAction = () => { type: 'DO_THIS' }; You need: 这样用: const myAction = () => ({ type: 'DO_THIS'}); Without wrapping the object in parentheses, you would not be using the short syntax. You will actually be defining a label for a string! 如果没有把对象包裹在圆括号里,你就不能使用缩写语法。实际上你会给字符串定义一个标签。 This is common inside the updater function of the setStatemethod because it needs to return an object. You need to wrap that object with parenthesis if you want to use the short arrow function syntax. 这在setState方法中的updater函数里很常见,因为其需要返回一个对象。如果想使用短箭头函数语法,你需要用圆括号包裹对象。 Instead of: 不要用: this.setState(prevState => { answer: 42 }); You need: 这样用: this.setState(prevState => ({ answer: 42 })); #### 11 — Not using the right capitalization of API elements and props #### 11 ——没有正确使用API元素和属性的大小写 It’s React.Component, not React.component. It’s componentDidMount, not ComponentDidMount. It’s usually ReactDOM, not ReactDom. 是React.Component,而不是React.component。是componentDidMount,而不是ComponentDidMount通常ReactDOM,而不是ReactDom。 Pay attention to the API capitalization that you need. If you use incorrect capitalization, the errors you’ll get might not clearly state what the problem is. 注意下你需要的API大写情况。如果使用了错误的大写,你得到的错误信息可能不会很明确。 When importing from react and react-dom, make sure that you’re importing the correct names and what you’re using is exactly the same as what you’re importing. ESLint can help you point out what is not being used. 当引用react 和 react-dom,确保你引用了正确的名字,以及你使用和你的引用的是完全一样的。ESLint可以帮你指出没有被使用的地方。 This problem is also common in accessing component props: 在处理组件属性时也会遇到这种问题:<Greeting userName="Max" /> // Inside the component, you need // 组件内部,你需要的话 props.userName If, instead of props.userName, you incorrectly use props.username or props.UserName, you will be using an undefined value. Pay attention to that, or better yet, make your ESLint configuration point these problems out as well. 如果你没有使用props.userName,而是props.username 或 props.UserName,你会相当于用了一个undefined的值。需要特别留意下这点,当然更好的是配置ESLint,让其也能指出这些问题。 #### 12— Confusing the state object with instance properties #### 12——把state对象和实例属性搞混了 In a class component, you can define a local state object and later access it with this: 在一个类组件里,你可以定义一个本地的state对象,之后可以用this获取之:class Greeting extends React.Component { **state** = { name: "World", }; render() { return `Hello ${**this.state**.name}` } }The above will output “Hello World”. 上面的代码会输出“Hello World”。 You can also define other local instant properties beside state: 你也可以不用state,定义其他本地实例属性:class Greeting extends React.Component { **user** = { name: "World", }; render() { return `Hello ${**this.user**.name}` } }The above will also output “Hello World”. 上面的代码也会输出“Hello World”。 The state instance property is a special one because React will manage it. You can only change it through setState and React will react when you do. However, all other instance properties that you define will have no effect on the rendering algorithm. You can change this.user in the above example as you wish and React will not trigger a render cycle in React. state实例属性特殊之处在于React会处理它。你只可以通过setState改变之,当你这样做时React会有相应的反馈。然而,所有其他你定义的实例属性会在渲染算法上没有效果。正如你希望的一样,你可以在上面的例子中改变this.user,React并不会触发渲染机制。 #### 13 — Confusing <tag/> with </tag> #### 13——把<tag/>和</tag>搞混了 Don’t misplace the / character in your closing tags. Admittedly, sometimes you can use <tag/> and other times you need </tag> 在闭合标签里放错/字符。不可否认,有时你可以使