Jen*_*Mok 16 javascript reactjs
import React, { Component } from 'react';
class Counter extends Component {
state = { value: 0 };
increment = () => {
this.setState(prevState => ({
value: prevState.value + 1
}));
};
decrement = () => {
this.setState(prevState => ({
value: prevState.value - 1
}));
};
render() {
return (
<div>
{this.state.value}
<button onClick={this.increment}>+</button>
<button onClick={this.decrement}>-</button>
</div>
)
}
}
Run Code Online (Sandbox Code Playgroud)
通常我看到的是人们在构造函数中执行this.state,如果他使用es6类.如果他不是,他可能使用getinitialstate函数放置状态.但是上面的代码(是的,它是一个工作代码),没有使用这两个.我有2个问题,这里的状态是什么?是一个局部变量?如果是,为什么它没有const?prevState来自哪里?为什么在setState中使用箭头函数?这不是很容易this.setState({value:'something'})吗?
T.J*_*der 17
我有两个问题,这是
state什么?
实例属性,如this.state = {value: 0};在构造函数中设置.它使用的公共类字段建议目前阶段2(所以是increment和decrement,这是实例字段,其值是箭头功能,所以他们关闭了this.)
是一个局部变量?
没有.
prevState来自哪里?为什么在setState中使用箭头函数?是不是很容易做到这一点.setState({value:'something'})?
从文档:
React可以将多个
setState()调用批处理为单个更新以提高性能.因为
this.props并且this.state可以异步更新,所以不应该依赖它们的值来计算下一个状态.例如,此代码可能无法更新计数器:
Run Code Online (Sandbox Code Playgroud)// Wrong this.setState({ counter: this.state.counter + this.props.increment, });要修复它,请使用第二种形式
setState()接受函数而不是对象.该函数将接收先前的状态作为第一个参数,并将更新作为第二个参数应用于道具:Run Code Online (Sandbox Code Playgroud)// Correct this.setState((prevState, props) => ({ counter: prevState.counter + props.increment }));
...这正是引用代码正在做的事情.这是错误的:
// Wrong
increment = () => {
this.setState({
value: this.state.value + 1
});
};
Run Code Online (Sandbox Code Playgroud)
...因为它依赖于this.state以上告诉我们的状态; 所以引用的代码改为:
increment = () => {
this.setState(prevState => ({
value: prevState.value + 1
}));
};
Run Code Online (Sandbox Code Playgroud)
这里的证明,以非显而易见的方式作出反应5批调用,为什么我们需要使用回调版本setState:在这里,我们increment和decrement被调用两次通过包含按钮跨度每次点击而不是由按钮一次(一次,连用).单击+ 一次应将计数器增加到2,因为increment调用两次.但是因为我们没有使用函数回调版本setState,所以它没有:其中一个调用increment成为无操作,因为我们使用的是陈旧this.state.value值:
class Counter extends React.Component {
state = { value: 0 };
increment = () => {
/*
this.setState(prevState => ({
value: prevState.value + 1
}));
*/
console.log("increment called, this.state.value = " + this.state.value);
this.setState({
value: this.state.value + 1
});
};
fooup = () => {
this.increment();
};
decrement = () => {
/*
this.setState(prevState => ({
value: prevState.value - 1
}));
*/
console.log("decrement called, this.state.value = " + this.state.value);
this.setState({
value: this.state.value - 1
});
};
foodown = () => {
this.decrement();
};
render() {
return (
<div>
{this.state.value}
<span onClick={this.fooup}>
<button onClick={this.increment}>+</button>
</span>
<span onClick={this.foodown}>
<button onClick={this.decrement}>-</button>
</span>
</div>
)
}
}
ReactDOM.render(
<Counter />,
document.getElementById("react")
);Run Code Online (Sandbox Code Playgroud)
<div id="react"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>Run Code Online (Sandbox Code Playgroud)
使用函数回调,它可以正常工作(没有调用increment成为no-ops):
class Counter extends React.Component {
state = { value: 0 };
increment = () => {
this.setState(prevState => {
console.log("Incrementing, prevState.value = " + prevState.value);
return {
value: prevState.value + 1
};
});
};
fooup = () => {
this.increment();
};
decrement = () => {
this.setState(prevState => {
console.log("Decrementing, prevState.value = " + prevState.value);
return {
value: prevState.value - 1
};
});
};
foodown = () => {
this.decrement();
};
render() {
return (
<div>
{this.state.value}
<span onClick={this.fooup}>
<button onClick={this.increment}>+</button>
</span>
<span onClick={this.foodown}>
<button onClick={this.decrement}>-</button>
</span>
</div>
)
}
}
ReactDOM.render(
<Counter />,
document.getElementById("react")
);Run Code Online (Sandbox Code Playgroud)
<div id="react"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>Run Code Online (Sandbox Code Playgroud)
在这种情况下,当然,我们可以查看该render方法并说"嘿,increment在点击期间会被调用两次,我最好使用回调版本setState." 但是,不是假设this.state在确定下一个状态时使用它是安全的,最佳做法是不要假设.在一个复杂的组件中,很容易以mutator方法的作者可能没有想到的方式使用mutator方法.因此,React作者的声明:
因为
this.props并且this.state可以异步更新,所以不应该依赖它们的值来计算下一个状态.
关于问题 2,请参考 Dan 的精彩回答:在这种情况下,我需要使用 setState(function) 重载吗?
不,它不是局部变量。这与this.state在构造函数中声明相同。
是的,在这种情况下,您可以只使用this.setState({ value: this.state.value + 1 }),结果将是相同的。
但请注意,通过使用函数式,setState您可以获得一些好处:
如果在外部声明 setState 函数,则可以重用它:
const increment = prevState => ({
value: prevState.value + 1
})
Run Code Online (Sandbox Code Playgroud)
现在如果你有几个组件需要使用这个功能,你可以在任何地方导入和重用逻辑。
this.setState(increment)
Run Code Online (Sandbox Code Playgroud)React 会压缩几个setState并批量执行它们。这可能会导致一些意外行为。请看下面的例子:
http://codepen.io/CodinCat/pen/pebLaZ
add3 () {
this.setState({ count: this.state.count + 1 })
this.setState({ count: this.state.count + 1 })
this.setState({ count: this.state.count + 1 })
}
Run Code Online (Sandbox Code Playgroud)
执行这个函数count只会加1
如果您使用函数式 setState:
http://codepen.io/CodinCat/pen/dvXmwX
const add = state => ({ count: state.count + 1 })
this.setState(add)
this.setState(add)
this.setState(add)
Run Code Online (Sandbox Code Playgroud)
如您所料,计数将 +3。
您可以在此处查看文档:https : //facebook.github.io/react/docs/react-component.html#setstate
| 归档时间: |
|
| 查看次数: |
9779 次 |
| 最近记录: |