状态(State)
State介绍
状态 state
:使用this.state
来引用,state
本身就是状态的意思,状态指的是事物所处的状况,状况就是环境。
通常使用state
存储简单的视图状态,比如说下拉框是否显示、单选 是否选中,或者需要自身去维护的变化数据等。
组件中用到的某个变量是不是应该作为组件State,可以通过下面的5条依据进行判断:
- 这个变量是否是通过
props
从父组件中获取?如果是,那么它不是一个状态。 - 这个变量是否在组件的整个生命周期中都保持不变?如果是,那么它不是一个状态。
- 这个变量是否可以通过其他状态(State)或者属性(Props)计算得到?如果是,那么它不是一个状态。
- 这个变量是否在组件的
render
方法中使用?如果不是,那么它不是一个状态。这种情况下,这个变量更适合定义为组件的一个普通属性,例如组件中用到的定时器,就应该直接定义为this.timer,而不是this.state.timer。 - 这个变量修改后,是否要更新组件?是,那么它是一个状态
设置默认state
class Test extends React.Component{
constructor(props){
super(props);
//默认状态
this.state = {
isShow:true
}
}
render(){
return <div style={display:this.state.isShow?'block':'none'}>This is component!</div>
}
}
修改state
常用的通知 React 数据变化的方法是调用 setState(data, callback)
。这个方法会合并(merge) data 到 this.state
,并重新渲染组件。渲染完成后,调用可选的 callback 回调。大部分情况下不需要提供 callback,因为 React 会负责把界面更新到最新状态。
this.setState({
isShow:false
})
setState会触发diff算法:判断state和页面结果的区别,是否需要更新
props基本使用
props
是组件(包括函数组件和class组件)间的内置属性,用其可以传递数据给子节点。
props
在传递数据的过程中,是只读的不能修改。
键值对
1.父组件调用子组件时传入属性
2.子组件直接通过this.props.属性名
即可拿到父组件传过来的值
//父组件
import React, { Component } from 'react'
import Child from './Child '
export default class Props extends Component {
state = {
title:"Hello world",
}
render() {
return (
<div>
<div><h3>首页</h3><Child title={this.state.title}></Child></div>
</div>
)
}
}
//子组件
import React, { Component } from 'react'
export default class Child extends Component {
render() {
console.log(this.props)
return (
<div>{this.props.title}</div>
)
}
}
展开语法{…props}
使用展开语法,React就会自动把对象中的变量和值当作是属性的赋值
//父组件
import React, { Component } from 'react'
import Child from './Child '
export default class Props extends Component {
state = {
title:"Hello world",
name:"React"
}
render() {
return (
<div>
<div><h3>首页</h3><Child {...this.state}></Child></div>
</div>
)
}
}
//子组件
import React, { Component } from 'react'
export default class Child extends Component {
render() {
console.log(this.props)
return (
<div>{this.props.title}</div>
)
}
}
props传函数
1.父组件调用子组件时传入函数属性
2.子组件直接通过this.props.fun()
即可调用父组件传过来的函数
//父组件
import React, { Component } from 'react'
import Child from './Child '
export default class Props extends Component {
state = {
title:"Hello world",
}
trigger(){
return "Hello React"
}
render() {
return (
<div>
<div><h3>首页</h3><Child title={this.state.title} fun={this.trigger}></Child></div>
</div>
)
}
}
//子组件
import React, { Component } from 'react'
export default class Child extends Component {
render() {
console.log(this.props)
return (
<div>{this.props.title}</div>
<div>{this.props.fun()}</div>
)
}
}
props验证
引入prop-types
用来校验父组件传递过来值的类型
propTypes/defaultProps
1.propTypes
用来验证类型和是否必传
2.defaultProps
:用来设置未传参时的默认值
import React, { Component } from 'react'
import PropTypes from "prop-types"
export default class Child extends Component {
render() {
return (
<div>{this.props.title}</div>
)
}
}
//类属性
Child.propTypes = {
title: PropTypes.string
}
Child.defaultProps= {
title: "Hello"
}
利用static
静态属性将验证写在类的里面
import React, { Component } from 'react'
import PropTypes from "prop-types"
export default class Child extends Component {
//类属性
static propTypes = {
title: PropTypes.string
}
static defaultProps= {
title: "Hello"
}
render() {
return (
<div>{this.props.title}</div>
)
}
}
PropTypes的种类
React PropTypes的种类有
PropTypes.array // 队列
PropTypes.bool.isRequired // Boolean 且必须
PropTypes.func // 函数
PropTypes.number // 数字
PropTypes.object // 对象
PropTypes.string // 字符串
PropTypes.node // 任何类型的: numbers, strings, elements 或者数组
PropTypes.element // React 元素
PropTypes.instanceOf(XXX) // 某种XXX类型的对象
PropTypes.oneOf(['foo', 'bar']) // 其中的一个字符串
PropTypes.oneOfType([React.PropTypes.string, React.PropTypes.array]) // 其中的一种类型
PropTypes.arrayOf(React.PropTypes.string) // 某种类型的数组(字符串)
PropTypes.objectOf(React.PropTypes.string) // 元素是字符串的对象
PropTypes.shape({ // 是否符合指定格式的对象
color: React.PropTypes.string,
fontSize: React.PropTypes.number
});
PropTypes.any.isRequired // 可以是任何格式,且必要。
// 自定义格式,不符合的时候放回Error
// 不要用`console.warn` 或者 throw, 因为它在`oneOfType` 的情况下无效
customPropType: function(props, propName, componentName) {
if (!/^[0-9]/.test(props[propName])) {
return new Error('Validation failed!');
}
}
属性和状态的区别
props
和 state
的相似点:
- 都是 js 对象,更新数据后会都会触发 render() 更新;
- 都可以设置默认值;
props
通过defaultProps
属性设置默认值;state
直接在定义的时候设置初始值;
props
和 state
的不同点:
- 属性是从父组件获取的,状态是在当前组件中定义的;
- 属性值只能由父组件修改,状态值只能由当前组件修改;
- 属性主要用于父组件和子组件间的通信,在组件内部是无法修改参数的;
- 状态是给自己用的,在内部初始化,被自己修改,在外部是不能修改的,内部通过 setState 修改,会触发render函数;
总结:state
和 props
主要的区别在于 props
是不可变的,而 state
可以根据与用户交互来改变。这就是为什么有些容器组件需要定义 state
来更新和修改数据。 而子组件只能通过 props
来传递数据。