reactjs - 如何防止重新渲染 react-redux
问题描述
在类别组件中,我从每个类别中渲染一个随机图像。我还为每个图像添加了一个 onClick 事件。当点击图片时,它会派发操作 getCategory(target.alt) 并且 DOM 会从点击的类别中呈现产品。我遇到的问题是,每次单击随机类别图像时,DOM 都会重新渲染,并且新的随机图像会出现在 DOM 上。如何防止这种重新渲染?下面是我的代码。
const Categories = ({selectedCategory}) => {
const isLoading = useSelector(state => state.productsReducer.isLoading);
const productsByCategory = useSelector(state =>
state.productsReducer.productsByCategories);
const getRandomProductsByCategory = () => {
const randomProducts = []
for(let categories in productsByCategory) {
const randomCategory = productsByCategory[categories][getRandomIndex(productsByCategory[categories].length)];
productsByCategory[categories].map(category => {
if(category === randomCategory) {
randomProducts.push(category)
}
})
}
return randomProducts;
}
return (
<div class='categories-container'>
{getRandomProductsByCategory().map(randomProduct => (
<img onClick={selectedCategory} src={randomProduct.image} />}
</div>
)
}
function App() {
const dispatch = useDispatch();
const category = useSelector(state => state.productsReducer.category)
useEffect(() => {
dispatch(getProducts())
}, [dispatch])
const handleCategoryClick = ({target}) => {
return dispatch(getCategory(target.alt))
}
return (
<>
{/* <ProductsList /> */}
<Categories selectedCategory={handleCategoryClick} />
{category.map(product => <img src={product.image} />)}
</>
)
}
const populateProductsStarted = () => ({
type: 'POPULATE_PRODUCTS/fetchStarted'
})
const populateProductsSuccess = products => ({
type: 'POPULATE_PRODUCTS/fetchSuccess',
payload: products
})
const populateProductsFailed = error => ({
type: 'POPULATE_PRODUCTS/fetchFailed',
error
})
export const getCategory = (category) => ({
type: 'GET_CATEGORY',
category
})
const getProducts = () => async dispatch => {
dispatch(populateProductsStarted())
try {
const response = await fetch(url)
if(response.ok) {
let jsonResponse = await response.json();
return dispatch(populateProductsSuccess(jsonResponse))
}
} catch (err) {
dispatch(populateProductsFailed(err.toString()))
}
}
const initialState = {
isLoading: false,
isError: null,
allProducts: [],
productsByCategories: {},
category: []
}
const productsReducer = (state=initialState, action) => {
switch(action.type) {
case 'POPULATE_PRODUCTS/fetchStarted':
return {
...state,
isLoading: true
}
case 'POPULATE_PRODUCTS/fetchSuccess':
return {
...state,
isLoading: false,
allProducts: action.payload,
productsByCategories: action.payload.reduce((accumulatedProduct, currentProduct) => {
accumulatedProduct[currentProduct.category] = accumulatedProduct[currentProduct.category] || [];
accumulatedProduct[currentProduct.category].push(currentProduct);
return accumulatedProduct;
}, {})
}
case 'POPULATE_PRODUCTS/fetchFailed':
return {
...state,
isError: action.error
}
case 'GET_CATEGORY':
return {
...state,
category: state.allProducts.filter(product => product.category === action.category)
}
default:
return state
}
}
解决方案
实现这一点的一种方法是通过 React 的useMemo
.
const images = React.useMemo(getRandomProductsByCategory().map(randomProduct => (
<img onClick={selectedCategory} src={randomProduct.image} />, [productsByCategory])
return (
<div class='categories-container'>
{images}
</div>
)
这将使 src 在重新渲染时保持一致。
推荐阅读
- php - 使用正则表达式捕获带有可选换行符的目标字符串
- ruby-on-rails - Bundler 找不到 gem "solidus_i18n" 的兼容版本:
- office365 - MS Graph API:“请求必须仅包含扩展更改。” 尝试创建日历事件时
- r - 如何从`sf::st_layers()`中提取层的名称?
- c# - 如何使用 JQuery dataicker 在 asp.net c# 中更改日期格式
- c - 是否有一个属性告诉编译器忽略缺少的返回语句?
- javascript - Node.js - 循环读取和写入数千/数百万个 JSON 文件
- utf-8 - Windows Server 2012 r2 中所有应用程序的活动代码页更改?
- php - 更新表单值不起作用 yii2
- python - 如何使用 .csv 文件在 Django 中填充多对多字段?