React Increment all counters at once:如何为多个组件重用处理函数
React Increment all counters at once: how to reuse handler function for multiple component
我有 3 个计数器按钮,但我想要一个单独的按钮,它会在 onClick 时将所有计数器加 1。实现它并让状态一次更改所有计数器的最佳方法是什么?我尝试添加 countAll
并合并所有计数,但语法似乎不正确,我不确定该怎么做。
import React, { Component } from 'react';
import Button from './components/Button';
class App extends Component {
constructor(props) {
super(props);
this.state = { counter1: 0, counter2: 0, counter3: 0 };
}
incrementCount1() {
this.setState(prevState => ({ counter1: prevState.counter1 + 1 }));
}
incrementCount2() {
this.setState(prevState => ({ counter2: prevState.counter2 + 1 }));
}
incrementCount3() {
this.setState(prevState => ({ counter3: prevState.counter3 + 1 }));
}
decrementCount1() {
this.setState(prevState => ({ counter1: prevState.counter1 - 1 }));
}
decrementCount2() {
this.setState(prevState => ({ counter2: prevState.counter2 - 1 }));
}
decrementCount3() {
this.setState(prevState => ({ counter3: prevState.counter3 - 1 }));
}
render() {
let { counter1, counter2, counter3 } = this.state
return (
<div className="App">
<h2>Count: { counter1 }</h2>
<Button title = { "+" } task = { () => this.incrementCount1(counter1) } />
<Button title = { "-" } task = { () => this.decrementCount1(counter1) } />
<h2>Count: { counter2 }</h2>
<Button title = { "+" } task = { () => this.incrementCount2(counter2) } />
<Button title = { "-" } task = { () => this.decrementCount2(counter2) } />
<h2>Count: { counter3 }</h2>
<Button title = { "+" } task = { () => this.incrementCount3(counter3) } />
<Button title = { "-" } task = { () => this.decrementCount3(counter3) } />
</div>
);
}
}
export default App;
示例使用 bracket notation and public class fields syntax
countOperation = (field, diff) => () => {
this.setState(prevState => ({ [field]: prevState[field] + diff }));
};
<button title={"+"} onClick={this.countOperation("counter1", 1)} />
<button title={"-"} onClick={this.countOperation("counter1", -1)} />
加法
如果愿意,您可以更进一步,将一组按钮打包到一个通用的 HOC 中,该 HOC 可以 return id
在某些回调上。
这样,如果有多个回调,你就不需要为每个元素多次绑定index/key
。
countOperation = diff => (e, id) => {
this.setState(prevState => ({ [id]: prevState[id] + diff }));
};
<CustomButton
id="counter1"
title={"+"}
onClick={this.countOperation(1)}
/>
class CustomButton extends React.Component {
render() {
const { id, title, onClick } = this.props;
return <button title={title} onClick={e => onClick(e, id)} />;
}
}
我真的很喜欢@keikai 的代码 reduction/DRY-principal 解决方案,但是如果您不想更改现有的状态形状,AND 如果您的现有状态是 只有个计数器,那么这将通过将状态作为对象.
进行操作来达到目的
获取状态对象,转换为条目数组,并将它们还原为代表下一个状态的对象,所有计数器都增加 incrementBy
数量。
incrementAll(incrementBy = 0) {
this.setState(prevState =>
Object.entries(prevState).reduce((counters, [counterKey, count]) => {
counters[counterKey] = count + incrementBy;
return counters;
}, {})
);
}
用法
<Button title = { "+ all" } task = { () => this.incrementAll(1) } />
<Button title = { "- all" } task = { () => this.incrementAll(-1) } />
我有 3 个计数器按钮,但我想要一个单独的按钮,它会在 onClick 时将所有计数器加 1。实现它并让状态一次更改所有计数器的最佳方法是什么?我尝试添加 countAll
并合并所有计数,但语法似乎不正确,我不确定该怎么做。
import React, { Component } from 'react';
import Button from './components/Button';
class App extends Component {
constructor(props) {
super(props);
this.state = { counter1: 0, counter2: 0, counter3: 0 };
}
incrementCount1() {
this.setState(prevState => ({ counter1: prevState.counter1 + 1 }));
}
incrementCount2() {
this.setState(prevState => ({ counter2: prevState.counter2 + 1 }));
}
incrementCount3() {
this.setState(prevState => ({ counter3: prevState.counter3 + 1 }));
}
decrementCount1() {
this.setState(prevState => ({ counter1: prevState.counter1 - 1 }));
}
decrementCount2() {
this.setState(prevState => ({ counter2: prevState.counter2 - 1 }));
}
decrementCount3() {
this.setState(prevState => ({ counter3: prevState.counter3 - 1 }));
}
render() {
let { counter1, counter2, counter3 } = this.state
return (
<div className="App">
<h2>Count: { counter1 }</h2>
<Button title = { "+" } task = { () => this.incrementCount1(counter1) } />
<Button title = { "-" } task = { () => this.decrementCount1(counter1) } />
<h2>Count: { counter2 }</h2>
<Button title = { "+" } task = { () => this.incrementCount2(counter2) } />
<Button title = { "-" } task = { () => this.decrementCount2(counter2) } />
<h2>Count: { counter3 }</h2>
<Button title = { "+" } task = { () => this.incrementCount3(counter3) } />
<Button title = { "-" } task = { () => this.decrementCount3(counter3) } />
</div>
);
}
}
export default App;
示例使用 bracket notation and public class fields syntax
countOperation = (field, diff) => () => {
this.setState(prevState => ({ [field]: prevState[field] + diff }));
};
<button title={"+"} onClick={this.countOperation("counter1", 1)} />
<button title={"-"} onClick={this.countOperation("counter1", -1)} />
加法
如果愿意,您可以更进一步,将一组按钮打包到一个通用的 HOC 中,该 HOC 可以 return id
在某些回调上。
这样,如果有多个回调,你就不需要为每个元素多次绑定index/key
。
countOperation = diff => (e, id) => {
this.setState(prevState => ({ [id]: prevState[id] + diff }));
};
<CustomButton
id="counter1"
title={"+"}
onClick={this.countOperation(1)}
/>
class CustomButton extends React.Component {
render() {
const { id, title, onClick } = this.props;
return <button title={title} onClick={e => onClick(e, id)} />;
}
}
我真的很喜欢@keikai 的代码 reduction/DRY-principal 解决方案,但是如果您不想更改现有的状态形状,AND 如果您的现有状态是 只有个计数器,那么这将通过将状态作为对象.
进行操作来达到目的获取状态对象,转换为条目数组,并将它们还原为代表下一个状态的对象,所有计数器都增加 incrementBy
数量。
incrementAll(incrementBy = 0) {
this.setState(prevState =>
Object.entries(prevState).reduce((counters, [counterKey, count]) => {
counters[counterKey] = count + incrementBy;
return counters;
}, {})
);
}
用法
<Button title = { "+ all" } task = { () => this.incrementAll(1) } />
<Button title = { "- all" } task = { () => this.incrementAll(-1) } />