Javascript 在按钮更改时不重新呈现React输入值

Javascript 在按钮更改时不重新呈现React输入值,javascript,reactjs,react-hooks,use-context,use-reducer,Javascript,Reactjs,React Hooks,Use Context,Use Reducer,我正在建立一个购物车项目 我尝试为购物车页面构建的一个功能是一个输入值,显示购物车中每个产品的数量(以便用户可以手动调整产品数量),以及输入两侧的一个按钮,用于将数量减少/增加1 这里是指向my codesandbox的链接,可以通过向购物车添加任何项目之一来重新创建问题: 我为手动调整输入字段而构建的逻辑按预期工作,但是当我单击递增/递减按钮时,它只是调整导航栏中购物车显示的项目数。输入字段没有更新-但是当查看React Developer Tools components调试器时,基础数量

我正在建立一个购物车项目

我尝试为购物车页面构建的一个功能是一个输入值,显示购物车中每个产品的数量(以便用户可以手动调整产品数量),以及输入两侧的一个按钮,用于将数量减少/增加1

这里是指向my codesandbox的链接,可以通过向购物车添加任何项目之一来重新创建问题:

我为手动调整输入字段而构建的逻辑按预期工作,但是当我单击递增/递减按钮时,它只是调整导航栏中购物车显示的项目数。输入字段没有更新-但是当查看React Developer Tools components调试器时,基础数量正在更新到正确的数字-它只是没有在DOM中重新提交输入值

有人能指出我哪里出了问题吗?我尝试在输入字段中将
defaultValue
切换到
value
,但这会阻止我手动调整输入


谢谢

你需要做两件事

<Quantity type='number' min='1' value={quantity} ref={itemRef} onChange={handleChange} />

  • 添加value prop以保持输入与上下文值同步

  • 将onBlur替换为
    onChange
    。您需要这样做,以确保更改输入中的值会更新您的上下文值

  • 问题
  • 您在
    AppLogic
    实用程序中严重改变了购物车项目的状态
  • 您正在为手动输入呈现“非受控”输入。这意味着它最初使用一个值进行渲染,但当您从外部更改“状态”时,该值表示它不会更新,因为它是不受控制的
  • 解决方案 AppLogic.js

    修复你的减速器工具,使它们不会改变购物车项目。更新它们时,您应该浅复制整个购物车项目数组,然后浅复制特定购物车项目

    export const checkIfItemInCart = (item, array, sum) => {
      const index = array.findIndex((object) => object.id === item.id);
      if (index !== -1) {
        const newArray = array.map((item, i) => i === index ? {
          ...item,
          quantity: item.quantity + (sum === "add" ? 1 : -1)
        } : item)
        if (!newArray[index].quantity) {
          return deleteItemLookup(item, newArray);
        }
        return newArray;
      }
      return array.concat(item);
    };
    
    export const customQuantityUpdate = (item, array, newQuantity) => {
      const index = array.findIndex((object) => object.id === item.id);
    
      const oldQuantity = array[index]?.quantity;
    
      // This could be more DRY, but edited to work
      if (newQuantity > oldQuantity) {
        return { array: array.map((item, i) => i === index ? {
          ...item,
          quantity: newQuantity
        } : item), type: "add", newQuantity, oldQuantity };
      } else if (newQuantity < oldQuantity) {
        return { array: array.map((item, i) => i === index ? {
          ...item,
          quantity: newQuantity
        } : item), type: "subtract", newQuantity, oldQuantity };
      } else {
        return { array, type: "", newQuantity, oldQuantity };
      }
    };
    
    演示

    谢谢。onBlur不能用于实现第二点有什么原因吗?我想我刚刚从react提供的错误中理解了原因:
    警告:您为表单字段提供了一个'value'属性,但没有'onChange'处理程序。这将呈现只读字段。如果字段应该是可变的,请使用“defaultValue”。否则,设置“onChange”或“readOnly”。
    但是,react也建议我不应该同时使用
    value
    defaultValue
    -
    arning:styled。input包含带有value和defaultValue属性的number类型的输入。输入元素必须受控或不受控(指定值属性或defaultValue属性,但不能同时指定两者)。决定使用受控或非受控输入元素,并移除其中一个道具。更多信息:https://reactjs.org/link/controlled-components
    对,您不能在输入上同时指定
    defaultValue
    value
    属性。您应该在此处使用
    value
    ,并可以安全地删除defaultValue。而且由于组件与上下文中的值同步。只有当组件失去焦点时,onBlur才会触发。因此,如果您从1-5更改并单击“外部”,您将使用最终值触发调度-
    5
    ,并且从1-4更改的值将不会反映在UI中,因为您没有进行调度。所以这里需要
    onChange
    来捕获您的每一个更改事件。谢谢Drew。这是我第一次使用
    useReducer
    ,我很高兴你了解了它。我将回顾并发表一些评论,这些评论将在本文的第一部分继续进行:
    constindex=array.findIndex((object)=>object.id==item.id)返回
    未定义的
    ,而不是
    -1
    。此外,我需要将'if(!newArray[index].quantity)`更改为'if(!newArray[index]?.quantity)`以防止引发未定义的错误。我仍在处理其余部分。@LearningPython
    Array.prototype.findIndex
    如果没有与谓词匹配的元素,肯定会返回
    -1
    。是
    Array.prototype.find
    可以返回未定义的。第二位是完全正确的,在访问属性之前,应该对
    newArray[index]
    进行空检查。更新了我的答案。很好,我错误地使用了
    find
    而不是
    findIndex
    。谢谢。@LearningPython我不知道您使用的浏览器是否与我不同,但我无法完全删除输入中的值。尽管如此,您可以使用
    const newQuantity=Math.max(1,Number(e.target.value)| 1)在
    onChange
    处理程序中强制执行最小值如果您能够以某种方式输入数字以外的内容(这会导致错误的
    NaN
    )或小于最小值的值。我更新了我的代码沙盒。
    <Quantity
      type="number"
      min="1"
      value={quantity}
      ref={itemRef}
      onChange={handleChange}
    />