React中handleIncrement正常,handleDecrement无响应问题求助
问题
正在观看Mosh的React教学视频,已实现Increment和Decrement处理器,二者代码逻辑相似,但handleIncrement可正常工作,handleDecrement却无响应,且控制台无任何报错信息。请问我哪里出错了?
App.js
import React, { Component } from 'react'; import NavBar from './components/navbar'; import Counters from './components/counters'; import './App.css'; class App extends Component { state = { counters: [ { id: 1, value: 4 }, { id: 2, value: 0 }, { id: 3, value: 0 }, { id: 4, value: 0 }, { id: 5, value: 0 }, ] }; constructor() { super(); console.log("App - Constructor"); } componentDidMount() { // make calls to server console.log("App - mounted!"); } handleDelete = (counterId) => { console.log('handle Delete: ', counterId); const counters = this.state.counters.filter(x => x.id !== counterId ); this.setState({ counters }); }; handleDecrement = (counter) => { const counters = [...this.state.counters]; const index = counters.indexOf(counter); counters[index] = {...counter}; counters[index].value--; this.setState(counters); console.log('decrement counter', counter); }; handleIncrement = (counter) => { const counters = [...this.state.counters]; const index = counters.indexOf(counter); counters[index] = {...counter}; counters[index].value++; this.setState({counters}); console.log('increment counter', counter); }; handleReset = () => { console.log('reset counters'); const counters = this.state.counters.map(c => { c.value = 0; return c; }); this.setState({counters}); }; render() { console.log("App - Rendered"); return ( <> <NavBar totalCounters={this.state.counters.filter(x => 0 < x.value).length} /> <main role="main" className="container"> <Counters counters={this.state.counters} onDecrement={this.handleDecrement} onDelete={this.handleDelete} onIncrement={this.handleIncrement} onReset={this.handleReset} /> </main> </> ); } }; export default App;
Counter.jsx
import React, { Component } from 'react'; import 'bootstrap/dist/css/bootstrap.css'; class Counter extends Component { componentDidUpdate(prevProps, prevState) { console.log("prevProps", prevProps); console.log("prevState", prevState); } componentWillUnmount() { } getBadgeClasses = () => { let badge = (this.props.counter.value === 0) ? 'bg-warning' : 'bg-primary'; return 'badge ' + badge + ' m-2'; } formatCount = () => { const { value: count } = this.props.counter; return count === 0 ? 'Zero' : count; } render() { console.log("Counter - Rendered"); return ( <div className='row'> <div className="col-1"> <span className={this.getBadgeClasses()}>{this.formatCount()}</span> </div> <div className="col"> <button onClick={() => this.props.onIncrement(this.props.counter)} className='btn btn-secondary btn-sm'>+</button> <button onClick={() => this.props.onDecrement(this.props.counter)} className='btn btn-secondary btn-sm m-2' disabled={this.props.counter.value === 0 ? 'disabled' : ''}>-</button> <button onClick={() => this.props.onDelete(this.props.counter.id)} className="btn btn-danger btn-sm">x</button> </div> </div> ); } } export default Counter;
Counters.jsx
import React, { Component } from 'react'; import Counter from './counter'; class Counters extends Component { render() { console.log("Counters - Rendered"); const { onReset, counters, onDecrement, onDelete, onIncrement } = this.props; return ( <div> <button onClick={onReset} className="btn btn-primary btn-sm m-2">Reset</button> {counters.map(counter => <Counter key={counter.id} onDecrement={onDecrement} onDelete={onDelete} onIncrement={onIncrement} counter={counter} /> )} </div> ); } } export default Counters;
问题分析与解决
核心问题在handleDecrement方法的setState调用上:
// 错误写法 this.setState(counters); // 正确写法(和handleIncrement保持一致) this.setState({ counters });
React的setState需要接收一个状态对象,你直接传入数组counters会导致状态更新失败,但因为语法合法,所以控制台不会抛出错误。修正后handleDecrement就能正常更新状态了。
另外补充一个规范问题:Counter组件中按钮的disabled属性应该用布尔值控制,而非字符串:
// 错误写法 disabled={this.props.counter.value === 0 ? 'disabled' : ''} // 正确写法 disabled={this.props.counter.value === 0}
虽然字符串'disabled'在HTML中会被视为真值,但React更推荐用布尔值控制这类属性,代码更符合React的设计规范。
内容的提问来源于stack exchange,提问作者user153923
相关产品推荐
相关产品推荐

