为了账号安全,请及时绑定邮箱和手机立即绑定

传递值的反应钩子问题|| defaultValue 和更新计数器

传递值的反应钩子问题|| defaultValue 和更新计数器

忽然笑 2022-10-21 10:19:16
在下面找到示例代码和屏幕截图。两个问题:counter没有正确更新,是否允许写类似的东西setCounter((prev) => { return { counter: prev.counter - value || 1 }});?setCounter(counter + value || 1)什么是正确的工作方式,在缺少实际值的情况下使用 1 ?在下面找到示例代码和屏幕截图。const Counter = (props) => {  const [counter, setCounter] = useState(0);  const handleCounterChange = (action, value) => {    switch (action) {      case "+":        setCounter(counter + value || 1);        break;      case "-":        setCounter(counter - value || 1);        break;      default:        setCounter(counter + value || 1);        break;    }  };  return (    <div className={classes.Counter}>      <CounterOutput value={counter} />      <CounterControl        label="+"        clicked={() => handleCounterChange("+")}      />      <CounterControl        label="-"        clicked={() => handleCounterChange("-")}      />      <CounterControl        label="+ 5"        clicked={() => handleCounterChange("+", 5)}      />      <CounterControl        label="- 5"        clicked={() => handleCounterChange("-", 5)}      />    </div>  );};export default Counter;
查看完整描述

3 回答

?
Qyouu

TA贡献1786条经验 获得超11个赞

问题setCounter(counter + value || 1);在于 JS 会先尝试计算,counter + value 然后再进行布尔测试。因此,例如,如果您的counter值为1并且减去 的值1,则结果为0,这是错误的,因此1将保存为 的新值counter。这可能不是你想要的。


console.log(100 + undefined || 1); // expect 101 but result is 1 
console.log(1 + -1 || 1); // expect 0 but result is 1


不过,您可以对优先级进行分组,即counter + (value || 1).


console.log(100 + (undefined || 1)); // 101

如果您只是想提供默认值 1 ,value那么您可以在签名中执行此操作。如果value未定义,它将被分配 的值1。并使用功能状态更新。


const handleCounterChange = (action, value = 1) => {

  switch (action) {

    case "+":

      setCounter(counter => counter + value);

      break;

    case "-":

      setCounter(counter => counter - value);

      break;

    default:

      setCounter(counter => counter + value);

      break;

  }

};

关于这种“reducer”类型模式的一个侧面说明是,如果该操作不是您专门处理的操作,则返回现有状态。


const handleCounterChange = (action, value = 1) => {

  switch (action) {

    case "+":

      setCounter(counter => counter + value);

      break;

    case "-":

      setCounter(counter => counter - value);

      break;

    default:

      // ignore, i.e. don't update state at all

      break;

  }

};


查看完整回答
反对 回复 2022-10-21
?
慕村9548890

TA贡献1884条经验 获得超4个赞

这里提出了几个优秀的重构。我肯定想通读这些建议并进行重构。


至于您不可预测的计数器的原因,假设单击参数正在进入您的状态更新函数,则存在操作顺序问题。考虑这种情况。


值为undefined

从上面代码的编写方式来看,当 value 为 时undefined,我们希望value在 state 中添加一个数字counter。由于操作顺序,这不是正在发生的事情。这个错误隐藏在明显的视线中,因为经常value和counter两者都是1,所以看起来状态没有改变。


> let value = undefined

undefined

> let counter = 1

undefined

> counter + value || 100

100

最后一条语句说“将计数器加起来undefined”,这NaN也是错误的。在这种情况下,结果将始终是“或”语句的另一端100。


使用括号更改操作顺序,并创建所需的行为。


> counter + (value || 100)

101


查看完整回答
反对 回复 2022-10-21
?
MM们

TA贡献1886条经验 获得超2个赞

本身不是一个答案,但不要使用额外的不必要的功能使您的代码过于复杂。您的逻辑是如此简单,添加额外的功能会使阅读变得更加复杂并添加奇怪的逻辑(默认值是什么?)



  return (

    <div className={classes.Counter}>

      <CounterOutput value={counter} />

      <CounterControl

        label="+"

        clicked={() => setCounter(state => state+1)}

      />

      <CounterControl

        label="-"

        clicked={() => setCounter(state => state-1)}

      />

      <CounterControl

        label="+ 5"

        clicked={() => setCounter(state => state+5)}

      />

      <CounterControl

        label="- 5"

        clicked={() => setCounter(state => state-5)}

      />

    </div>

  );


如果你想再干一点,你总是可以做这样的事情:



  const change = by => () => setCounter(count => count+by)


  return (

    <div className={classes.Counter}>

      <CounterOutput value={counter} />

      <CounterControl

        label="+"

        clicked={change(1)}

      />

      <CounterControl

        label="-"

        clicked={change(-1)}

      />

      <CounterControl

        label="+ 5"

        clicked={change(5)}

      />

      <CounterControl

        label="- 5"

        clicked={change(-5)}

      />

    </div>

  );


查看完整回答
反对 回复 2022-10-21
  • 3 回答
  • 0 关注
  • 253 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号