【问题标题】:React Increment all counters at once: how to reuse handler function for multiple componentReact 一次增加所有计数器:如何为多个组件重用处理函数
【发布时间】:2020-03-15 04:31:27
【问题描述】:

我有 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;

【问题讨论】:

    标签: javascript reactjs counter


    【解决方案1】:

    使用bracket notationpublic 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 可以在特定回调时返回 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)} />;
      }
    }
    

    【讨论】:

    • 我认为setState 需要通过prevState 传递一个回调,类似于优雅地处理更新的问题。
    【解决方案2】:

    我真的很喜欢 @keikai 的代码缩减/DRY-principal 解决方案,但是如果您不想更改现有状态形状,并且如果您现有的状态是 only em> 计数器,那么这将通过操作状态作为对象来达到目的。

    获取状态对象,转换为条目数组,然后将它们还原为表示下一个状态的对象,所有计数器都以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) } />
    

    【讨论】:

    • 谢谢,这正是我想要的。
    • @JabbatheHutt 太棒了!如果足够,请接受作为答案。
    猜你喜欢
    • 2020-08-27
    • 2023-03-16
    • 2021-09-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多