reactjs - 更改单个项目时重新渲染整个列表
问题描述
我有一个产品列表,我想添加更多数据,例如价格和数量。问题是当我开始输入时我失去了输入焦点,因为整个列表正在重新呈现。我有一个简单的小提琴复制那段代码:
const App = () => {
// List of products
const [products, setProducts] = React.useState([
{
title: 'My Product',
},
{
title: 'My Product 2',
}
]);
// Simple debug to track changes
React.useEffect(() => {
console.log('PRODUCTS', products);
}, [products]);
const ProductForm = ({ data, index }) => {
const handleProductChange = (name, value) => {
const allProducts = [...products];
const selectedProduct = {...allProducts[index]};
allProducts[index] = {
...selectedProduct,
[name]: value
};
setProducts([ ...allProducts ]);
}
return (
<li>
<h2>{data.title}</h2>
<label>Price:</label>
<input type="text" value={products[index].price} onChange={(e) => handleProductChange('price', e.target.value)} />
</li>
);
}
return <ul>{products.map((item, index) => <ProductForm key={item.title} index={index} data={item} />)}</ul>;
}
ReactDOM.render(
<App />,
document.getElementById('container')
);
https://jsfiddle.net/lucasbittar/zh1d6y37/23/
我尝试了一堆我在这里找到的解决方案,但没有一个真正代表我所拥有的。
谢谢!
解决方案
问题
您已经在ProductForm
内部定义了App
它,因此每个渲染周期都会重新创建它,即每次渲染它都是一个全新的组件。
解决方案
移动ProductForm
到外部定义。这现在存在handleProductChange
无法访问App
的功能范围products
状态的问题。这里的解决方案是handleProductChange
返回App
并更新函数签名以使用index
. 用作data.price
输入值,您可以为此属性提供后备值或提供初始状态。
建议:命名输入name="price"
并简单地从事件对象中使用它。
const ProductForm = ({ data, index, handleProductChange }) => {
return (
<li>
<h2>{data.title}</h2>
<label>Price:</label>
<input
name="price" // <-- name input field
type="text"
value={data.price || ''} // <-- use data.price or fallback value
onChange={(e) => handleProductChange(e, index)} // <-- pass event and index
/>
</li>
);
}
const App = () => {
// List of products
const [products, setProducts] = React.useState([
{
title: 'My Product',
},
{
title: 'My Product 2',
}
]);
// Simple debug to track changes
React.useEffect(() => {
console.log('PRODUCTS', products);
}, [products]);
// Update signature to also take index
const handleProductChange = (e, index) => {
const { name, value } = e.target; // <-- destructure name and value
const allProducts = [...products];
const selectedProduct = {...allProducts[index]};
allProducts[index] = {
...selectedProduct,
[name]: value
};
setProducts([ ...allProducts ]);
}
return (
<ul>
{products.map((item, index) => (
<ProductForm
key={item.title}
index={index}
data={item}
handleProductChange={handleProductChange} // <-- pass callback handler
/>)
)}
</ul>
);
}
ReactDOM.render(
<App />,
document.getElementById('container')
);
推荐阅读
- matplotlib - plt.title 粗体删除空格
- javascript - 无法加载插件 Tinymce
- sql - 如何将 SQL 最大值(日期)计算添加到 SQL 表中?
- firebase - How to convert Bigquery repeated record into a column?
- javascript - My discord bot send the embed message when someone reply something
- sql-server - How to get Java exception thrown when connection closed and using Tomcat?
- windows - How to create event and listen for event in powershell
- android - Get Android app launch source from Application context
- node.js - Lighthouse tests are failing with Fastify SSR
- node.js - How can i use ACK method on pubsub topic? (@nestjs-google-pubsub)