react笔记03
状态提升
当遇到需要同时获取多个子组件数据,或者两个组件之间需要相互通讯的情况时,需要把子组件的state数据提升至共同的父组件中保存。之后父组件可以通过props将状态数据传递到子组件当中。这样应用当中所有组件的状态数据就能够更方便地同步共享了。
为Board组件添加构造函数,将Board组件的初始状态设置为长度为9的空值数组:
class Board extends React.Component {
constructor(props) {
super(props);
this.state = {
squares: Arrary(9).fill(null),
};
}
renderSquare(i) {
return <square value={i} />
}
}
相反,从Board组件向Square组件传递一个函数,当Square被点击的时候,这个函数就会被调用。接着,我们将Board组件的renderSquare方法改写成如下效果:
renderSquare(i) {
return (
<square
value={this.state.squares[i]}
onClick={() => this.handleClick(i)}
/>
);
}
从Board组件向Square组件中传递两个props参数:value和onClick。onClickprop是一个Square组件点击事件监听函数。
class Square extends React.Component {
render() {
return (
<button
className="square"
onClick={() => this.props.onClick()}
>
{this.props.value}
</button>
)
}
}
不可变性在React中非常重要
我们通过使用.slice()方法创建了数组的一个副本,而不是直接修改现有的数组。
一般来说,有两种改变数据的方式。第一种方式时直接修改变量的值,第二种方式是使用新的一份数据替换旧数据
直接修改数据
var player = {score:1,name:'jeff'};
var newPlayer = Object.assign({},player,{score:2});
// player的值没有改变,但是newPlayer的值是{score:2,name:'jeff'}
// 使用对象展开语法,就可以写成:
// var newplayer = {.../player,score:2};
不直接修改(或改变底层数据)这种方式和前一种方式的结果是一样的,这种方式有以下几点好处:
简化复杂的功能##:
不可变性使得复杂的特性更容易实现。
跟踪数据的改变##:
如果直接修改数据,那么就很难跟踪到数据的改变。跟踪数据的改变需要可变对象可以与改变之前的版本进行对比,这样整个对象树都需要被遍历一次。
跟踪不可变数据的变化相对来说容易,如果发现对象变成了一个新对象,那么我们就可以说对象发生改变了。
确定在React中何时重新渲染##
不可变性最主要的优势在于他可以帮助我们在React中创建pure components。我们可以很轻松的确定不可变数据是否发生了改变,从而确定何时对组件进行重新渲染。
函数组件
接下来我们把Square组件重写为一个函数组件
如果想写的组件只包含一个render方法,并且不包含state,那么使用函数组件就会更简单。我们不需要定义一个继承于React.Component的类,我们可以定义一个函数,这个函数接收props作为参数,然后返回需要渲染的元素。函数组件写起来不像class组件那么繁琐,很多组件都可以使用函数组件来写。
把Square类替换成下面的函数:
function Square(props) {
return (
<button className="square" onClick={props.onClick}>
{props.value}
</button>
)
}
我们把两个this.props都替换成了props。