前言 React通过管理状态实现对组件的管理,通过this.setState()方法更新state,触发render()方法重新渲染页面,而在更新前有一个shouldComponentUpdate可以控制state更新是否触发render,方便不必要的渲染,而state里最好放入与渲染有关的属性,而渲染无关的使用class的属性对象保存使用即可。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 class Demo extends Component{ constructor(props){ super(props); this.state = {name:"zhang" }; // state this.objState = {currPage:0}; // 不必要渲染的对象使用 } changePage (){ this.objState.currPage++; } render (){ return ( <div>{this.state.name}</div> ) } }
state注意事项 1、使用state是要遵循react的规则,state是不可变的,需要使用特定的函数更新state,如state在constructor定义后不能对它直接进行赋值操作,而是要使用setState,否则不会触发渲染render,而是直接修改了state,在下次使用setState后直接覆盖掉。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 class Demo extends Component{ constructor(props){ super(props); this.state = {name:"zhang" }; // state this.objState = {currPage:0}; // 不必要渲染的对象使用 } changePage=()=>{ // 这是错误的操作 this.state.name = "测试" ; // 正确操作 this.setState({name: "ceshi" }); } render (){ return ( <div onClick={changePage}>{this.state.name}</div> ) } }
2、setState是异步的 由于react的setState的源码里,会先把state的更新推进队列里,等所有的state都进入后才会进行render的渲染操作,而所以在setState后不要直接获取state的数据,因为那些还是旧数据,而是要等调用栈结束后执行渲染操作再获取更新后state,但shouldComponentUpdate与componentWillUpdate接受的参数是更新后state,所以这些在渲染前的钩子函数可以在接收参数里获取更新的state与props,而setState的异步是代码执行顺序实现的,代码里都是同步的 。
但由于setState在一般的调用时都会放到任务队列里,而把setState的使用放在setTimeout这些异步调用的回调函数里时不会放到任务队列里,而是直接调用,所以在setTimeout这些回调函数里可以直接获取到更新的state。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 class ItemOne extends Component { constructor(props) { super(props); this.state={name:"zhang" }; } change=()=>{ this.setState({name:"vvv" }); setTimeout(()=>{ this.setState({name:"xxx" }); console.log("time:" +this.state.name); // xxx },0) } shouldComponentUpdate(props, state){ console.log(this.state.name) return true ; } componentWillUpdate(props, state){ console.log(state); console.log(this.state.name); } componentDidUpdate (){ console.log(this.state.name) } render () { return ( <div className='itemOne' > <div onClick={this.change}>{this.state.name}</div> </div> ) } } // 打印 // zhang // {name: "vvv" } // zhang // vvv
3、不要在shouldComponentUpdate与componentWillUpdate使用 在shouldComponentUpdate与componentWillUpdate使用setState会造成死循环,所以浏览器都会在控制台报错。
1 2 // 报错信息 Maximum update depth exceeded. This can happen when a component repeatedly calls setState inside componentWillUpdate or componentDidUpdate. React limits the number of nested updates to prevent infinite loops.
4、不涉及渲染state 由于state的更新都会触发render渲染,而有些状态是不需要触发渲染的,那么可以使用一些普通对象保存,而不是使用state管理,因为state与普通对象的差别在于会触发页面的渲染。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 class Demo extends Component{ constructor(props){ super(props); this.state = {name:"zhang" }; // state this.objState = {currPage:0}; // 不必要渲染的对象使用 } changePage=()=>{ this.objState.currPage++; } render (){ return ( <div onClick={changePage}>{this.state.name}</div> ) } }
5、componentWillReceiveProps 当一个组件从父组件接受参数;只要父组件的render函数被重新执行了,子组件的这个生命周期就会被执行; (如果这个组件第一次存在于父组件中,不会执行,如果这个组件之前存在于父组件中,才会执行) 所以无论props使用更新,只要父组件渲染了那么就会触发这个函数
最后更新时间:2019-04-19 23:50:56