如何使用setState方法来避免警告按摩



我有这个示例程序。我正在尝试添加两个数字,并将它们显示在显示部分。代码完全按照我希望的方式工作。但问题是,当我运行该程序时,我会收到一条警告信息,上面写着";不要直接改变状态。使用setState(("。现在,如果我把代码中的this.state改成this.setState,程序就不能正常工作。例如,当我点击一个数字时,它直到第二次点击才显示在显示器上。如何使用唯一的setState来避免警告消息来解决此问题?谢谢

class App extends React.Component {
constructor(props){
super(props);
this.state = {
display: '',
inputs: '',
result: '',
currentNumber: '',
previousNumber: '',
operator: ''
}
}
inputNumber = numberbtn => {
this.state.currentNumber = this.state.currentNumber.toString() + numberbtn.toString()
this.state.inputs = this.state.currentNumber 
this.setState({result: this.state.inputs})
}
inputOperator = operatorBtn => {
if(this.state.currentNumber === '')return
if(this.state.previousNumber!== ''){
this.calculateInput()
}
this.state.operator = operatorBtn
this.state.previousNumber = this.state.currentNumber
this.state.inputs = this.state.previousNumber + operatorBtn
this.state.result = this.state.inputs
this.setState({result: this.state.inputs})
this.setState({display: this.state.result})
this.setState({result: ''})
this.state.currentNumber = ''
this.state.inputs = ''
}
calculateInput = () => {
if(this.state.operator === "+"){
this.state.result = parseFloat(this.state.previousNumber) + 
parseFloat(this.state.currentNumber)
this.setState({
result: parseFloat(this.state.previousNumber) + 
parseFloat(this.state.currentNumber)
})
}

this.state.currentNumber = this.state.result
this.state.operator = undefined
this.state.previousNumber = ''
this.state.inputs = ''
this.setState({display: ''})

}
render() {
return (
<div className = "container">
<div className = "display">
<DisplayComponent display={this.state.display}/>
<DisplayComponent result={this.state.result}/>
</div>
<button onClick={() =>this.inputNumber(1)}>1</button>
<button onClick={() =>this.inputNumber(2)}>2</button>
<button onClick={() =>this.inputNumber(3)}>3</button>
<button onClick={() =>this.inputOperator('+')}>+</button>
<button className = "span" onClick={() =>this.calculateInput('=')}>=</button>
</div>
)
}
}
export default App

除了直接状态突变/操作的明显问题之外,我认为您还有一些不必要的状态和移动部件。

代码/逻辑可以简化为一个显示字符串(display(、两个操作数(currentNumberpreviousNumber(和一个运算符(operator(。

算法很简单:

  1. 构建当前编号并显示字符串,直到输入运算符为止
  2. 保存操作员并将当前号码移动到上一个号码
  3. 建立当前数字并显示字符串,直到运算符或"="输入。
    1. 如果输入了运算符,则计算结果并重复步骤2
    2. 如果"="输入计算结果,清除运算符,并更新显示和当前编号

代码:

const DisplayComponent = ({ display }) => <div>{display}</div>;
const initialState = {
display: "",
currentNumber: "",
previousNumber: "",
operator: ""
};
class App extends React.Component {
state = { ...initialState };
inputNumber = (numberbtn) => {
this.setState((prevState) => ({
display: prevState.display + numberbtn,
currentNumber: prevState.currentNumber + numberbtn
}));
};
inputOperator = (operatorBtn) => {
if (this.state.currentNumber === "") return;
if (this.state.operator) {
this.calculateInput();
}
this.setState((prevState) => ({
display: prevState.display + operatorBtn,
currentNumber: "",
operator: operatorBtn,
previousNumber: prevState.currentNumber
}));
};
calculateInput = () => {
const { operator, previousNumber, currentNumber } = this.state;
if (!(previousNumber && currentNumber)) return;
let result = Number(previousNumber);
const v2 = Number(currentNumber);
switch (operator) {
case "+":
result += v2;
break;
case "-":
result -= v2;
break;
case "*":
result *= v2;
break;
case "/":
result /= v2;
break;
default:
throw new Error("invalid opearator");
}
this.setState({
display: result,
currentNumber: String(result),
operator: ""
});
};
render() {
return (
<div className="container">
<div className="display">
<DisplayComponent display={this.state.display} />
</div>
<div>
{[...Array(10).keys()].map((val) => (
<button key={val} onClick={() => this.inputNumber(val)}>
{val}
</button>
))}
<button onClick={() => this.setState(initialState)}>Clear</button>
</div>
<div>
{["+", "-", "*", "/"].map((key) => (
<button key={key} onClick={() => this.inputOperator(key)}>
{key}
</button>
))}
</div>
<button className="span" onClick={() => this.calculateInput("=")}>
=
</button>
</div>
);
}
}
const rootElement = document.getElementById("root");
ReactDOM.render(
<App />,
rootElement
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.13.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.13.1/umd/react-dom.production.min.js"></script>
<div id="root" />

this.state.inputs = this.state.currentNumber 
this.setState({result: this.state.inputs})

这是一个很好的例子。首先,你只需在this.state.input中赋值,就会出现你所说的错误。但第二个是正确的用法。所以,把所有和第一行相似的行都改成第二行。你有很多这样的陈述,你需要全部改变。希望起作用。

我为你编辑代码,你可以检查它。另一点需要注意的是,你永远不会释放结果的值,所以我们在字符串中的旧值之后得到新值。这就是为什么我们每次在开始时都设置空字符串的结果。你可以去看看。

class App extends React.Component {
constructor(props){
super(props);
this.state = {
display: '',
inputs: '',
result: '',
currentNumber: '',
previousNumber: '',
operator: ''
}
}
inputNumber = numberbtn => {
this.setState({currentNumber : this.state.currentNumber.toString() + numberbtn.toString()})
this.setState({inputs : this.state.currentNumber })
this.setState({result: this.state.inputs})
}
inputOperator = operatorBtn => {
if(this.state.currentNumber === '')return
if(this.state.previousNumber!== ''){
this.calculateInput()
}
this.setState({operator :operatorBtn})
this.setState({previousNumber :this.state.currentNumber})
this.setState({inputs :this.state.previousNumber + operatorBtn})
this.setState({result : this.state.inputs})

this.setState({display: this.state.result})
this.setState({result: ''})
this.setState({currentNumber: ''})
this.setState({inputs : ''})
}
calculateInput = () => {
if(this.state.operator === "+"){


this.setState({
result: parseFloat(this.state.previousNumber) + 
parseFloat(this.state.currentNumber)
})
}

this.setState({currentNumber:this.state.result})
this.setState({operator :undefined})
this.setState({previousNumber: ''})
this.setState({inputs: ''})
this.setState({display: ''})

}
render() {
return (
<div className = "container">

<button onClick={() =>this.inputNumber(1)}>1</button>
<button onClick={() =>this.inputNumber(2)}>2</button>
<button onClick={() =>this.inputNumber(3)}>3</button>
<button onClick={() =>this.inputOperator('+')}>+</button>
<button className = "span" onClick={() =>this.calculateInput('=')}>=</button>
<p>{this.state.result}</p>
</div>
)
}
}
ReactDOM.render(
<App  />,
document.body
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

最新更新