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) } />