React只更新它需要更新的部分
React DOM 会将元素和它的子元素与它们之前的状态进行比较,并只会进行必要的更新来使 DOM 达到预期的状态。
正确使用State
- 不要直接修改state
- state的更新可能是异步的
- 出于性能考虑,React 可能会把多个
setState()
调用合并成一个调用。 - 因为
this.props
和this.state
可能会异步更新,所以你不要依赖他们的值来更新下一个状态。 - 解决这个问题,可以让
setState()
接收一个函数而不是一个对象。
- 出于性能考虑,React 可能会把多个
- state的更新会被合并
数据是向下流动的
这通常会被叫做“自上而下”或是“单向”的数据流。任何的 state 总是所属于特定的组件,而且从该 state 派生的任何数据或 UI 只能影响树中“低于”它们的组件。
事件处理
必须谨慎对待 JSX 回调函数中的 this
,在 JavaScript 中,class 的方法默认不会绑定 this
。如果你忘记绑定 this.handleClick
并把它传入了 onClick
,当你调用这个函数的时候 this
的值为 undefined
。
class Toggle extends React.Component {
constructor(props) {
super(props);
this.state = {isToggleOn: true};
// 为了在回调中使用 `this`,这个绑定是必不可少的
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
this.setState(prevState => ({
isToggleOn: !prevState.isToggleOn
}));
}
render() {
return (
<button onClick={this.handleClick}>
{this.state.isToggleOn ? 'ON' : 'OFF'}
</button>
);
}
}
觉得使用bind麻烦,两种解决方法:
- 使用 public class fields 语法
- 在回调中使用箭头函数
- 如果该回调函数作为 prop 传入子组件时,这些组件可能会进行额外的重新渲染。
传递参数
在循环中,通常我们会为事件处理函数传递额外的参数。例如,若 id
是你要删除那一行的 ID,以下两种方式都可以向事件处理函数传递参数:
<button onClick={(e) => this.deleteRow(id, e)}>Delete Row</button>
<button onClick={this.deleteRow.bind(this, id)}>Delete Row</button>
上述两种方式是等价的,分别通过箭头函数和 Function.prototype.bind
来实现。
在这两种情况下,React 的事件对象 e
会被作为第二个参数传递。如果通过箭头函数的方式,事件对象必须显式的进行传递,而通过 bind
的方式,事件对象以及更多的参数将会被隐式的进行传递。
列表&Key
如果列表项目的顺序可能会变化,我们不建议使用索引来用作 key 值,因为这样做会导致性能变差,还可能引起组件状态的问题。
一个好的经验法则是:在 map()
方法中的元素需要设置 key 属性。
表单
总的来说,这使得 <input type="text">
, <textarea>
和 <select>
之类的标签都非常相似—它们都接受一个 value
属性,你可以使用它来实现受控组件。
注意 你可以将数组传递到
value
属性中,以支持在select
标签中选择多个选项: <select multiple={true} value={['B', 'C']}>