@[toc]
一、文章参考
二、正确地使用 State
setState(updater, [callback]) API介绍
- 只传递一个对象(需要改变的state属性)
setState({
"改变state的key": "新的值"
})
- 参数一为带有形式参数的 updater 函数:
setState((state, props) => {
return {
"改变state的key": "新的值"
}
})
- setState() 的第二个参数为可选的回调函数
它将在 setState 完成合并并重新渲染组件后执行。通常,我们建议使用 componentDidUpdate() 来代替此方式。
react 想要更新视图只能用 setState( ) 方法
关于 setState() 这里有三件事情需要知道
-
不要直接更新状态, 而是使用 setState()
-
状态更新是异步的React 可以将多个setState() 调用合并成一个调用来提高性能。
-
this.props 和 this.state 都可能是异步更新的,你不应该依靠它们的值来计算下一个状态。
请使用第二种形式的
setState() 来接受一个函数而不是一个对象。该函数将接收先前的状态作为第一个参数,将此次更新被应用时的props做为第二个参数
三、案例
3.1 setState()接收对象(修改普通的input 表单输入值)
- 使用
React.createClass创建React组件
var NoLink = React.createClass({
getInitialState:function(){
return {message:''}
},
handelChange:function(event){
console.log(event.target);
this.setState({message:event.target.value})
},
render:function(){
var mess = this.state.message;
return (
<div>
<input type="text" onChange={this.handelChange} value={mess} />
<b>{mess}</b>
</div>
)
}
});
React.render(<NoLink />,document.body);
- 使用
class创建组件
import React from 'react'
// 直接引入scss文件,转为了css
import styleObj from './CustomerRegistPage.module.scss'
import { Input, message } from 'antd'
import mimaImg from '@/asserts/images/icons/icon_mima@1x.png'
import chakanmimaImg from '@/asserts/images/icons/icon_chakanmima@1x.png'
import BaseComponent from '@/core/BaseComponent'
export default class CustomerRegistPage extends BaseComponent {
constructor (props) {
super(props)
this.state = {
studentRePassword: ''
}
}
getJSXImg (imgSrc) {
return <img src={imgSrc} style={{ width: 24, height: 24 }} />
}
// input 表单绑定的事件
userInputChange (type, event) {
const value = event.target.value
this.setState({
[type]: value
})
}
render () {
const inputStyle = {
width: 400,
height: 44
}
const { studentRePassword } = this.state
return (
<Input
placeholder="请确认密码"
value={studentRePassword}
onChange={this.userInputChange.bind(this, 'studentRePassword')}
style={inputStyle}
prefix={this.getJSXImg(mimaImg)}
suffix={this.getJSXImg(chakanmimaImg)}
/>
)
}
}
3.2 setState()接收函数(定时器倒计时)
错误写法
export default class EditSuccess extends BaseComponent {
constructor (...args) {
super(...args)
this.state = {
timer: null,
name: 'huangbiao',
timeCounter: 60
}
}
componentDidMount () {
// 第一进来 timeCounter 的值为60
const { timeCounter } = this.state
this.state.timer = setInterval(() => {
// 类似于闭包
// 执行定时器的方法,timeCounter 的值为60一直没有变化,所以timeCounter-1 的值为59就不会变化
this.setState({
timeCounter: timeCounter - 1
})
}, 1000)
}
componentWillUnmount () {
clearInterval(this.state.timer)
}
render () {
const { timeCounter, name } = this.state
return (
<div className={styleObj.EditSuccess}>
{timeCounter}
</div>
)
}
}
闭包,将timeCounter 的值固化了,永远都为 60
将setState()参数改为函数,state代表当前state值的状态,返回值为需要修改的state对象
componentDidMount () {
this.state.timer = setInterval(() => {
this.setState((state, props) => {
return {
timeCounter: state.timeCounter - 1
}
})
}, 1000)
}
或者,每次都从this.state中获取值,不要采用闭包
componentDidMount () {
this.state.timer = setInterval(() => {
this.setState({
timeCounter: this.state.timeCounter - 1
})
}, 1000)
}
3.3 下拉列表的二级联动,使用setState回调函数
选择行业之后,就要根据选择的行业去查询对应的岗位,因为setState是异步的,无法保证setState字段'industryItemCode'之后值一定发生了变化,就有可能导致getPostListByCode方法中的 industryItemCode 值还是之前没有变化的,因此,触发getPostListByCode方法必须要在industryItemCode变化之后调用
export default class ExpertRegistForm extends BaseComponent {
constructor (props) {
super(props)
this.state = {
industryItemCode: '', // 选中行业的code
// 所在行业
industryArr: [],
interviewerDetailList: [ // 选择的细分领域
// {
// companyPostName: 'Java',
// companyPostId: 3
// }
],
// 根据行业找到的领域
postListArr: []
}
this.getPostListByCode = this.getPostListByCode.bind(this)
this.selectIndustryChange = this.selectIndustryChange.bind(this)
}
// 根据行业Code获取所有职业信息
getPostListByCode () {
const { industryItemCode } = this.state
getPostListByCodeService(industryItemCode).then((res) => {
this.setState({
// postListArr: transformMapTreeData(res.data)
postListArr: res.data
})
})
}
// select 表单绑定的事件
selectIndustryChange (type, value) {
this.setState({
[type]: value
}, () => {
this.getPostListByCode()
})
}
render () {
const {
interviewerDetailList, interviewerUsername, companyName, industryItemName,
interviewerTagsList,
industryItemCode, interviewerWorkYear, interviewerEmail, interviewerPassword,
interviewerRePassword, interviewTimeZone, timeZoneArr, industryArr, postListArr
} = this.state
return (
<>
<div className={styleObj['ExpertRegistForm--form__item']}>
{/* <Input placeholder="所在行业" style={inputStyle} prefix={this.getJSXImg(hangyeImg)} /> */}
<Select
placeholder="所在行业"
defaultValue={industryItemCode}
value={industryItemCode}
style={{ width: 400 }}
size="large"
onChange={this.selectIndustryChange.bind(this, 'industryItemCode')}
>
{industryArr.map((item, index) => {
return (
<Option
value={item.industryItemCode}
key={item.industryItemName}
>
{item.industryItemName}
</Option>
)
})}
</Select>
</div>
<div className={styleObj['ExpertRegistForm--form__item']}>
{/* <Input placeholder="细分领域" style={inputStyle} prefix={this.getJSXImg(xifenImg)} /> */}
<Select
mode="multiple"
placeholder="细分领域"
defaultValue={interviewerDetailList}
style={{ width: 400 }}
size="large"
onChange={this.userSelectChange.bind(this, 'interviewerDetailList')}
>
{postListArr.map((item, index) => {
return (
<Option value={item.industryItemId} key={item.industryItemId}>{item.industryItemName}</Option>
)
})}
</Select>
</div>
</>
)
}
}