setState方法
- setstate资源:方法详解
- 细节注意:事实上,setState 方法与包含在其中的执行是一个很复杂的过程,从 React 最初的版本到现在,也有无数次的修改。它的工作除了要更动 this.state 之外,还要负责触发重新渲染,这里面要经过 React 核心 diff 算法,最终才能决定是否要进行重渲染,以及如何渲染。而且为了批次与效能的理由,多个 setState 呼叫有可能在执行过程中还需要被合并,所以它被设计以延时的来进行执行是相当合理的。
在 React 的 setState 函数实现中,会根据一个变量 isBatchingUpdates 判断是直接更新 this.state 还是放到 队列中回头再说,而 isBatchingUpdates 默认是 false,也就表示 setState 会同步更新 this.state,但是,有 一个函数 batchedUpdates,这个函数会把 isBatchingUpdates 修改为 true,而当 React 在调用事件处理函 数之前就会调用这个 batchedUpdates,造成的后果,就是由 React 控制的事件处理过程 setState 不会同步
更新 this.state。
由 React 控制的事件处理过程 setState 不会同步更新 this.state!
也就是说,在 React 控制之外的情况, setState 会同步更新 this.state! this.setState是异步,所以在this.setState之后立即调用this.state是获取不到最新的数据的,那么怎么获取最新的数据呢?有三个方法:
1.回调函数callback
this.setState({val: this.state.val+1},() => {console.log(this.state.val)});
2.componentDidUpdate
componentDidUpdate(){console.log(this.state.val);}
在this.setState之后去componentDidUpdate函数中调用,此时的this.state已经更新
3.将this.setState放入setTimeout函数中
let self = this;setTimeout(function () {self.setState({val:self.state.val+1});console.log(self.state.val);})
在setTimeout函数中,在this.setState之后this.state是立即更新的,所以也可以获取到更新后的数据。
- setState(newState [,callback])
setState是更新组件中的state内容。但是,它一般是异步的,倘若设置完就使用新的state可能得不到我们想要的结果,例如:
this.state = {init:1}this.setState({init:2})console.log(this.state.init); // 输出结果为:1//----------但是,我们明明是想要结果为 2------so~~~回调函数就解决了这个问题~~~-------this.setState({init:2}, ()=>{console.log(this.state.init); // 输出结果为:2})
可以看出,set state中的回调函数作用大致和componentDidUpdate生命周期类似。
setState方法将组件的更改排入队列,并且告诉React使用更改后的状态更新组件;而React会在必要的时候一起更新几个组件,而不是每次都立即进行更新。所以,需要将setState视为请求,而不是一个立即执行函数。建议使用componentDidUpdate代替回调函数这种逻辑
setState存在隐患,由于它是异步的,并且有可能是同一周期同一批次进行处理,会出现问题:后一个更改替代了前一个更改,原本想要quantity +2,由于异步批次处理,只加1.
Object.assign(previousState,{quantity: state.quantity + 1},{quantity: state.quantity + 1},...)
倘若下一个状态取决于先前的状态,不建议使用以下的形式。
//wrongthis.setState({counter: this.state.counter + this.props.increment,});
而是:
//correctthis.setState((prevState, props) => ({counter: prevState.counter + props.increment}));
组件
组件名称必须以大写字母开头。
React 会将以小写字母开头的组件视为原生 DOM 标签。例如,
setState() 的三件事:
不要直接修改State
例如,此代码不会重新渲染组件:
// Wrongthis.state.comment = 'Hello';
而是应该使用setState():
// Correctthis.setState({comment: 'Hello'});
构造函数是唯一可以给 this.setstate 赋值的地方:
State的更新可能是异步的
出于性能考虑,React 可能会把多个setState()调用合并成一个调用。
因为 this.props 和 this.setstate 可能会异步更新,所以你不要依赖他们的值来更新下一个状态。
例如,此代码可能会无法更新计数器:
// Wrongthis.setState({counter: this.state.counter + this.props.increment,});
要解决这个问题,可以让 setState()接收一个函数而不是一个对象。这个函数用上一个 state 作为第一个参数,将此次更新被应用时的 props 做为第二个参数:
// Correctthis.setState((state, props) => ({counter: state.counter + props.increment}));
上面使用了箭头函数,不过使用普通的函数也同样可以:
// Correctthis.setState(function(state, props) {return {counter: state.counter + props.increment};});
State的更新会被合并
当你调用 setState() 的时候,React 会把你提供的对象合并到当前的 state。
例如,你的 state 包含几个独立的变量:
constructor(props) {super(props);this.state = {posts: [],comments: []};}
然后你可以分别调用setState() 来单独地更新它们:
componentDidMount() {fetchPosts().then(response => {this.setState({posts: response.posts});});fetchComments().then(response => {this.setState({comments: response.comments});});}
这里的合并是浅合并,所以this.setState({comments}) 完整保留了this.state.posts , 但是完全替换了this.state.comments 。
Chosen 对 DOM 做的操作
如果你在一个 之后增加一个独立的具有它自身显示表现的 DOM 节点。然后它会在值变化的时候触发 jQuery 事件来通知我们这些变化。
以下代码是我们最终要实现的效果:
function Example() {return (<Chosen onChange={value => console.log(value)}><option>vanilla</option><option>chocolate</option><option>strawberry</option></Chosen>);}
为了简化,我们将它实现为 uncontrolled component
首先,我会创建一个空的组件,它的 render() 函数我们返回一个包含 使用一个额外的
