反应输入值不会在按钮更改时重新呈现
React input value not re-rendering on button change
我正在构建一个购物车项目。
我试图为我的购物车页面构建的功能之一是显示购物车中每个产品数量的输入值(以便用户可以手动调整产品数量)以及一个按钮输入的任一侧 decrement/increment 数量乘以 1.
这是我的 codesandbox link,可以通过将任何项目添加到购物车来重新创建问题:
https://codesandbox.io/s/yqwic
我为手动调整输入字段而构建的逻辑按预期工作,但是当我单击 increment/decrement 按钮时,它只会调整导航栏中显示的购物车中的项目数量。输入字段没有更新 - 但是当查看 React-Developer-Tools 组件调试器时,基础数量正在更新为正确的数字 - 它只是没有重新呈现 DOM.[=13= 中的输入值]
谁能指出我可能哪里出错了?我尝试在输入字段中将 defaultValue
切换为 value
,但这使我无法手动调整输入。
谢谢
你需要做两件事,
<Quantity type='number' min='1' value={quantity} ref={itemRef} onChange={handleChange} />
添加 value 属性以使您的输入与上下文值保持同步。
将 onBlur 替换为 onChange
。您需要这样做以确保更改输入中的值会更新您的上下文值。
问题
- 您在
AppLogic
实用程序中严重改变了您的购物车项目状态。
- 您正在为手动输入呈现“不受控制”的输入。这意味着它最初呈现一个值,但是当您从外部更改“状态”时,该值表示它不会更新,因为它不受控制。
解决方案
AppLogic.js
修复您的 reducer 实用程序,使它们不会改变购物车项目。更新它们时,您应该浅复制整个购物车项目数组,然后然后浅复制特定的购物车项目。
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 };
}
};
CartItem.js
使用 value
属性和 onChange
属性将输入转换为完全受控的输入。
<Quantity
type="number"
min="1"
value={quantity}
ref={itemRef}
onChange={handleChange}
/>
演示
我正在构建一个购物车项目。
我试图为我的购物车页面构建的功能之一是显示购物车中每个产品数量的输入值(以便用户可以手动调整产品数量)以及一个按钮输入的任一侧 decrement/increment 数量乘以 1.
这是我的 codesandbox link,可以通过将任何项目添加到购物车来重新创建问题:
https://codesandbox.io/s/yqwic
我为手动调整输入字段而构建的逻辑按预期工作,但是当我单击 increment/decrement 按钮时,它只会调整导航栏中显示的购物车中的项目数量。输入字段没有更新 - 但是当查看 React-Developer-Tools 组件调试器时,基础数量正在更新为正确的数字 - 它只是没有重新呈现 DOM.[=13= 中的输入值]
谁能指出我可能哪里出错了?我尝试在输入字段中将 defaultValue
切换为 value
,但这使我无法手动调整输入。
谢谢
你需要做两件事,
<Quantity type='number' min='1' value={quantity} ref={itemRef} onChange={handleChange} />
添加 value 属性以使您的输入与上下文值保持同步。
将 onBlur 替换为
onChange
。您需要这样做以确保更改输入中的值会更新您的上下文值。
问题
- 您在
AppLogic
实用程序中严重改变了您的购物车项目状态。 - 您正在为手动输入呈现“不受控制”的输入。这意味着它最初呈现一个值,但是当您从外部更改“状态”时,该值表示它不会更新,因为它不受控制。
解决方案
AppLogic.js
修复您的 reducer 实用程序,使它们不会改变购物车项目。更新它们时,您应该浅复制整个购物车项目数组,然后然后浅复制特定的购物车项目。
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 };
}
};
CartItem.js
使用 value
属性和 onChange
属性将输入转换为完全受控的输入。
<Quantity
type="number"
min="1"
value={quantity}
ref={itemRef}
onChange={handleChange}
/>