如何防止重新渲染react-redux

时间:2021-01-29 22:47:53

标签: reactjs redux react-redux onclick rerender

在类别组件中,我渲染了每个类别的随机图像。我还为每个图像添加了一个 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
    }
}

1 个答案:

答案 0 :(得分:1)

实现这一目标的一种方法是通过 React 的 useMemo 提供的记忆。

const images = React.useMemo(getRandomProductsByCategory().map(randomProduct => (
                <img onClick={selectedCategory} src={randomProduct.image} />, [productsByCategory])
return (
        <div class='categories-container'>
           {images}
        </div>
    )

这将使 srcs 在重新渲染时保持一致。