【问题标题】:React - Fire a function after user has selected a valueReact - 在用户选择一个值后触发一个函数
【发布时间】:2021-08-01 02:00:20
【问题描述】:

用户选择了一个值之后触发函数的最佳方式是什么。例如,用户快速单击数字 10,然后停止,然后触发包含该值的函数。可能类似于控制台日志。 debounce 是正确的方法吗?我在逻辑上遇到了一些问题,非常感谢您的帮助。

在下面的代码中,我可以让addToCart 函数在多次点击后只触发一次,这正是我想要的。但是amount 已经过时了。在代码中,您可以看到amount 可能会发生变化,例如cartAmount 有值时。但是,在去抖动时,它只会将 amount 的值视为 1

这是我的代码

const QuantitySelectorComponent = (props) => {
const {
    cartAmount,
} = props;

const [amount, setAmount] = useState(1);

useEffect(() => {
    if (cartAmount) {
    setAmount(cartAmount); 
    }
}, [cartAmount]);

const increment = useMemo(() => debounce(() => {
    setAmount(amount => amount + 1);
    addToCart(amount)
}, 2000), [addToCart]);

const decrement = useMemo(() => debounce(() => {
    setAmount(amount => amount - 1);
    addToCart(amount)
}, 2000), [addToCart]);


return(
    <StyledQuantityWrapper>
        <StyledQuantityButton disabled={ amount <= 0 } 
            onClick={decrement} >
            &mdash;
        </StyledQuantityButton>
        <StyledQuantityInput onFocus={onFocus} onBlur={onBlur} className="quantity-input__screen" type="number" value={ amount } />
        <StyledQuantityButton disabled={ amount <= 0 } 
            onClick={increment} >
            &#xff0b;
        </StyledQuantityButton>
    </StyledQuantityWrapper>
)

}

导出默认的QuantitySelectorComponent;

【问题讨论】:

  • 你的意思是当用户快速点击 10 次然后记录第 10 次而不是 10 次?就像用户在特定时间后点击然后记录每次点击一样?
  • 当然,消除“onChange”回调似乎是合乎逻辑的。如果您要求“X 的最佳方式”,那么我建议您重新措辞,以使其更加客观(相对于主观,即固执己见)。
  • 点击一个数字,在本例中为 10。然后触发一个函数,对该数字执行某些操作。我正在构建一个数量选择器,在用户完成选择数字后添加到购物车。现在,每次点击都会触发。这电话太多了。我希望有一个功能在用户完成选择时触发。我以前从未使用过 debounce,现在遇到了一些问题
  • 您能否分享一个代码示例在您的问题中,您尝试在函数调用中使用去抖动实用程序?有些库(即 lodash)具有去抖动功能,或者您可以推出自己的简单版本。
  • 嗨,是的,很抱歉。我添加了自己的代码并试图澄清情况。我正在使用 lodash 的 debounce

标签: javascript reactjs react-hooks


【解决方案1】:

问题

我在您的代码中看到的问题是您正在对状态更新进行去抖动,而不是在每次状态更新后对要调用的函数进行去抖动。

建议

您希望消除addToCart 函数的抖动并允许所有正常的 React 状态更新正常发生。为了避免任何陈旧的外壳,请使用依赖于amount 状态的useEffect 挂钩来调用addToCart 的去抖动版本。

例子

const QuantitySelectorComponent = (props) => {
  const firstRender = useRef(true);
  const { cartAmount } = props;

  const [amount, setAmount] = useState(1);

  useEffect(() => {
    if (cartAmount) {
      setAmount(cartAmount);
    }
  }, [cartAmount]);

  const debouncedAddToCart = useMemo(() => debounce(addToCart, 2000), []);

  useEffect(() => {
    if (firstRender.current) {
      // don't call addToCart on the initial render
      firstRender.current = false;
      return;
    }
    debouncedAddToCart(amount);
  }, [amount, debouncedAddToCart]);

  const increment = (value) => () => setAmount((c) => c + value);

  return (
    <div>
      <button disabled={amount <= 0} onClick={increment(-1)}>
        &mdash;
      </button>
      <input
        onFocus={onFocus}
        onBlur={onBlur}
        className="quantity-input__screen"
        type="number"
        value={amount}
        onChange={e => setAmount(Number(e.target.value))}
      />
      <button disabled={amount < 0} onClick={increment(1)}>
        &#xff0b;
      </button>
    </div>
  );
};

【讨论】:

  • 哦,有趣!但是我收到Uncaught TypeError: Expected a function 错误
  • @DonegalBoyVancouver 你在哪里得到这个错误?
  • 嗯,它在组件中。控制台在告诉我在哪里方面并不是很有帮助。我以为可能是onClick,所以我尝试添加onClick={() =&gt; {increment(-1)}} ,但不好。
  • @DonegalBoyVancouver 哦,我将增量/减量转换为一个单一的柯里化函数,如果这会让你在任何事情上绊倒的话。我的链接代码框有错误吗?或代码中的其他地方?你能分享完整的错误吗?
  • 当然。我也收到了这个Warning: Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in a useEffect cleanup function.
【解决方案2】:

您可以使用 useEffect 挂钩来关注状态计数的变化,并在计数为 10 时触发您的函数。

const {useState, useEffect} = React;

function Counter() {
  // Set the initial count state to zero, 0
  const [count, setCount] = useState(0);
  
  useEffect(() => {
    if (count === 10) {
      // fire your function
      console.log('--------', count);
    }
  }, [count]);

  // Create handleIncrement event handler

【讨论】:

  • 感谢您的回答,但不幸的是它并没有解决我的问题。当用户完成选择任何数字时,我正在尝试找到一种方法来触发该功能。我只是以 10 为例。我正在尝试构建一个添加到购物车的应用程序,当用户完成他们的选择后,该函数会获取该值并对其进行处理,例如将该值用作添加到购物车的数量
  • 那么,你怎么知道用户选择了最后一个数字并且不会加或减任何数字?也许你可以在其他事件函数中触发你的函数,例如。用户点击并提交购物车订单。
  • 答案涉及使用debounce。但我无法让它工作
  • 功能其实就在这里。 realcanadiansuperstore.ca/… 将商品添加到购物车,然后修改数量。您会看到添加到购物车仅在用户完成选择数量时触发
  • 我已经更新了问题并添加了我自己的代码来阐明我想要做什么
猜你喜欢
  • 2020-05-15
  • 1970-01-01
  • 1970-01-01
  • 2022-08-04
  • 1970-01-01
  • 2021-08-15
  • 1970-01-01
  • 2018-01-08
相关资源
最近更新 更多