对于数据,我们只关心三点:如何初始化,如何读,如何写
props
外部数据
props 的作用
-
接受外部数据
- 只能读不能写
- 外部数据由父组件传递
-
接受外部函数
- 在恰当的时候,调用该函数
- 该函数一般是父组件的函数
初始化
class A extends React.Component {
constructor(props) {
super(props)
}
render(){}
}
这样做之后,this.props
就是外部数据 对象的地址
怎么读
通过 this.props.xxx
来读
语法
class A extends React.Component {
constructor(props) {
super(props)
}
render(){
return <div onClick={this.props.onClick}>
{this.props.name}
<div>
{this.props.children}
</div>
</div>
}
}
示例
class A extends React.Component {
constructor(props) {
super(props)
this.state = { x: 1 }
}
onClick = () => {
this.setState({
x: this.state.x + 1
})
}
render() {
return (
<div>
这是 A
<button onClick={this.onClick}>+1</button>
<B name={this.state.x} />
</div>
)
}
}
class B extends React.Component {
render() {
return (
<div>n: {this.props.name}</div> // 使用 this.props.name 来读
)
}
}
怎么写
- 永远不要去改 props!
- 外部数据,就应该由外部更新
state & setState
内部数据
初始化
class A extends React.Component {
constructor(props) {
super(props)
this.state = {
user: {
name: 'heycn',
age: 18
}
}
}
render() {
return ( ... )
}
}
怎么读
通过
this.state.xxx
来读
怎么写
通过
this.setState(???, fn)
来写
参考这篇博客:「React」牛x的前端这么写 setState()
推荐第二种方法
方法一
重点看第
onClick1
的代码
class A extends React.Component {
constructor(props) {
super(props)
this.state = { x: 1 }
}
onClick1 = () => {
this.setState({ x: this.state.x + 1 })
}
render() {
return (
<div>
x: {this.state.x}
<button onClick={this.onClick1}>+1</button>
</div>
)
}
}
方法二
重点看
onClick2
的代码
class A extends React.Component {
constructor(props) {
super(props)
this.state = { x: 1 }
}
onClick2 = () => {
this.setState(state => ({ x: state.x + 1 }))
}
render() {
return (
<div>
x: {this.state.x}
<button onClick={this.onClick2}>+1</button>
</div>
)
}
}
总结
-
读用
this.state
this.state.xxx.yyy.zzz
-
写用
this.setState(???, fn)
this.setState(newState, fn)
- 注意:
setState
不会立刻改变this.state
,会在当前代码运行之后,再去更新this.state
,从而触发 UI 更新 this.setState((state, props) => newState, fn)
- 这种法师的
state
反而更容易理解 fn
会在写入成功后执行
-
写时会 shallow merge
setState
会自动更新state
与旧state
进行第一层的合并