举个栗子:
class greeting extends React.Component {
// ...
}
如果您尝试渲染 ,则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按钮元素。 React在这种情况下不会提醒你。
2.使用单引号代替倒引号
用倒引号(`...`)创建的字符串与用单引号('...')创建的字符串不同。
在大多数键盘上,可以使用Tab键上方的键来输入倒引号(`)字符。
当我们需要在该字符串中包含动态表达式时,我们会使用倒引号创建一个字符串(不需要使用字符串连接)。
`这是一个字符串模板文字,可以包含表达式`
'这只是一个字符串,这里不能包含表达式'
假设你想要一个字符串,它显示当前时间: "Time is ..."
// 当前时间
const time = new Date().toLocaleTimeString();
// 当使用常规字符串(单引号或双引号)时,
// 您需要使用字符串连接:
'Time is ' + time
// 使用倒引号时,
// 您可以使用${}在字符串中插入时间
`Time is ${time}`
另外,当使用字符串文本(倒引号)时,您可以创建一个跨越多行的字符串:
const template = `I
CAN
SPAN
Multiple Lines`;
这是不能使用普通字符串做到的
3.使用React.PropTypes
PropTypes对象已从React中删除。它以前可以作为React.PropTypes使用,但是现在你不能再使用它了。
现在需要这样使用:
1. 将新的prop-types包添加到您的项目中:npm install prop-types
2. 导入包:`import PropTypes from 'prop-types'`
然后你可以使用它。例如:PropTypes.string
如果你错误地使用了React.PropTypes
,你会得到如下错误:TypeError: Cannot read property 'string' of undefined
4.不使用教程正在使用的版本
当你看到一些教程或视频并跟着他们做DEMO时,请务必确保你正在使用的包或工具版本是正确的。通常,使用每种工具的最新版本是安全的选择,但如果教程有点老,则可能会遇到一些版本问题。
为了安全期间,推荐使用和教程一样的主版本,比如教程使用的是React.js 16那么就不推荐你使用React.js 15
对于Node.js这点很重要,如果使用老版本的Node.js你可能会面临重大问题。例如你跟着一些教程他们使用了Object.values
你使用的Node.js 6.x,这个方法就并不存在那么就需要更新到Node.js 7.x
5.疑惑的function
和class
你能告诉我以下代码有什么问题吗?
class Numbers extends React.Component {
const arrayOfNumbers = _.range(1, 10);
// ...
}
上面的代码是无效的,因为在JavaScript类的主体内部,你不能自由地做任何事情。您只能使用有限的语法定义方法和属性。
这有点让人迷惑,因为类语法中使用的{}看起来像普通的块作用域,但事实并非如此。
在基于function
组件中,您可以自由地做任何事情:
// 完全可以做任何事情
const Number = (props) => {
const arrayOfNumbers = _.range(1, 10);
// ...
};
6.将数字作为字符串传递
您可以使用字符串传递一个prop值:
<Greeting name="World" />
如果需要传递数值,请不要使用字符串:
// 不要这样做
<Greeting counter="7" />
``
相反,你需要使用大括号将你要传递的数值括起来
```javascript
// 这样做
<Greeting counter={7} />
使用{7}
在Greeting
组件中,this.props.counter
将会获得一个数值型的7
对于数学运算是安全的。如果你把它当作"7"
,然后把它当作一个数字运算,你可能会遇到意想不到的结果你懂的。
7.忘记创建环境变量
一些项目依赖于shell环境变量的存在来启动。如果您在不需要环境变量的情况下运行这些项目,它们将尝试为它们使用未定义的值,并可能会给您一些神秘的错误。
例如如果一个项目连接了MongoDB数据库,它可能会使用像process.env.MONGO_URI这样的环境变量来连接它。这使得项目可以在不同的环境中使用不同的MongoDB实例。
在本地运行连接到MongoDB的项目,你必须先导出一个MONGO_URI环境变量。例如,如果您有一个本地MongoDB在27017端口上运行,那么在运行该项目之前您需要执行此操作:
export MONGO_URI = "mongodb://localhost:27017/mydb"
你可以使用grep
查看项目源代码找出它需要什么环境变量才能正常工作。
8.混淆花括号{}和圆括号()
不能这样
return {
something();
};
应该这样
return (
something();
);
第一个将尝试返回一个对象,而第二个将正确调用something()
并且返回该函数返回的内容
因为在JSX中任何 都将转换为函数调用,所以在返回任何JSX时,这个问题都是适用的
这个问题在箭头函数的短语法中也很常见
不能这样
const Greeting = () => {
<div>
Hello World
</div>
};
应该这样
const Greeting = () => (
<div>
Hello World
</div>
);
9.不用圆括号包装对象
当您想要创建一个返回一个普通对象的短箭头函数时,上面的花括号和括号问题也会令人困惑
不要这样
const myAction = () => { type: 'DO_THIS' };
需要这样
const myAction = () => ({ type: 'DO_THIS'});
不将对象用括号括起来,myAction
函数不会得到一个正确的普通对象。
这在setState
方法的updater函数中很常见,因为它需要返回一个对象。如果要使用短箭头函数语法,则需要用圆括号包装该对象。
不要这样
this.setState(prevState => { answer: 42 });
需要这样
this.setState(prevState => ({ answer: 42 }));
10.API
和props
不使用正确的大小写
它是React.Component
不是React.component
。它是componentDidMount
不是ComponentDidMount
。还有ReactDOM
不是ReactDom
请注意您需要的API大小写。如果您使用不正确的大写字母,那么您将得到的错误可能无法清楚地说明问题所在。
当从react
和react-dom
导入时,确保导入正确的名称,使用的名称与导入的内容完全相同。ESLint可以帮助你指出不正确的地方。
访问组件props
时,这个问题也很常见:
<Greeting userName="Max" />
// 在组件内部,你需要这样
props.userName
如果不是props.userName
,您错误地使用props.username
或props.UserName
,你会得到undefined
值。需要注意这一点,或者更好的方法是,配置您的ESLint让他帮你处理这些问题。
11.混淆state
对象和实例属性
在类组件中,您可以定义一个组件state
对象,然后使用以下方法访问它:
class Greeting extends React.Component {
state = {
name: "World",
};
render() {
return `Hello ${this.state.name}`;
}
}
以上将输出“Hello World”
你也可以在定义state
附近定义一个实例属性
class Greeting extends React.Component {
user = {
name: "World",
};
render() {
return `Hello ${this.user.name}`;
}
}
以上也会输出“Hello World”。
state
属性是一个特殊的属性,因为React将管理它,你只能通过setState
来改变它,而React会在你做这件事时做出对应的反应。但是,您定义的所有其他实例属性都不会影响渲染算法。您可以根据需要在上面的示例中更改this.user
,React不会触发渲染周期
12.混淆<tag/>
和</tag>
不要在结束标记中放错/
字符。无可否认,有时您可以使用<tag />
和其他需要</ tag>
。
在HTML中,有一种叫做“自闭合标签”,这些是代表没有任何子节点的元素的标签。例如,img
标签是一个自闭合标签:
<img src="..." />
// 你不需要使用 <img></img>
一个div
标签可以有子元素,所以你会使用开始和结束标签:
<div>
Children here...
</div>
这同样适用于React组件。如果组件具有子内容,则可能如下所示:
<Greeting>Hello!</Greeting>
如果组件没有子元素,可以使用自闭合组件
// 下面两种方法都是有效的
<Greeting></Greeting>
<Greeting />
下面使用是无效的
// 错误
<Greeting><Greeting />
如果你放错了/
字符,你会得到如下错误:
Syntax error: Unterminated JSX contents
13.不绑定函数作用域
我最后保存了这个,因为这是一个很大的问题,也是一个很常见的问题。
您可以在React组件中定义类方法,然后在组件的render方法中使用它们。例如:
class Greeting extends React.Component {
whoIsThis() {
console.dir(this); // "this"是whoIsThis的调用者
return "World";
}
render() {
return `Hello ${this.whoIsThis()}`;
}
}
ReactDOM.render(<Greeting />, mountNode);
在render
方法内部,我使用了this.whoIsThis
方法调用了whoIsThis()方法,这个this
关键字是指与表示组件的DOM元素相关联的组件实例,也就是Greeting
组件
React内部会确保其类方法中的this
引用到组件实例,但是当你使用whoIsThis方法的引用时,JavaScript不会自动绑定到组件实例。
console.dir
这行中打印出的this
会指向组件实例,因为我们是从render
方法内部调用的。执行上面的代码时,您应该在控制台中看到Greeting
对象:
但是,当您在延迟执行通道中使用相同的方法时,如事件处理程序,调用者将不再明确,并且console.dir
行不指向组件实例。
请参阅下面的代码和输出(单击后)
在上面的代码中,当你点击字符串时,React调用whoIsThis方法,但它不会让你访问里面的组件实例。这就是为什么当我们点击字符串时你会得到undefined
的原因。如果你的类方法需要访问像this.props
和this.state
这样的东西,这是一个问题。它根本无法工作。
对于这个问题,有许多解决方案。您可以将方法封装在内联函数中,或者使用.bind
调用来强制方法记住它的调用者。对于不经常更新的组件,两者都可以。您还可以通过在类的构造函数中而不是在render方法中对绑定方法进行优化。但是,此方法的最佳解决方案是通过Babel启用ECMAScript class-fields
段功能(仍然是第3阶段),并仅为处理程序使用箭头函数:
class Greeting extends React.Component {
whoIsThis = () => {
console.dir(this);
}
render() {
return (
<div onClick={this.whoIsThis}>
Hello World
</div>
);
}
}
将按预期工作:
目前就是这些了,感谢阅读。