Как позволить компоненту перерисовываться во время изменения реквизита

Я хочу добиться эффекта при изменении PRODUCTS (во время нажатия кнопки), список также меняется с изменением первой категории на «ха-ха».

Вся цель состоит в том, чтобы позволить компоненту перерисовываться во время изменения реквизита. Но похоже, что это не работает. Ниже приведен код.

import React, { useState } from 'react';
import ReactDOM from 'react-dom';

const FilterableProductTable = (props) =>{
    return (

        <ul>
            {props.products.map((product) =>
                (<li>{product.category}</li>)
            )}
        </ul>
    );
}

const PRODUCTS = [
    { category: 'Sporting Goods', price: '$49.99', stocked: true, name: 'Football' },
    { category: 'Sporting Goods', price: '$9.99', stocked: true, name: 'Baseball' },
    { category: 'Sporting Goods', price: '$29.99', stocked: false, name: 'Basketball' },
    { category: 'Electronics', price: '$99.99', stocked: true, name: 'iPod Touch' },
    { category: 'Electronics', price: '$399.99', stocked: false, name: 'iPhone 5' },
    { category: 'Electronics', price: '$199.99', stocked: true, name: 'Nexus 7' }
];

const Home = () => {
    const [productData, changeProduct] = useState(PRODUCTS);
    const handleClick = () => {
        PRODUCTS[0].category = 'haha';
        changeProduct(PRODUCTS);
        console.info(PRODUCTS);
    };
    return (
        <>
            <button onClick = {handleClick}>haha</button>
            <FilterableProductTable products = {productData} />
        </>
    );
};

export default Home;

Вы можете попробовать это здесь:

Как позволить компоненту перерисовываться во время изменения реквизита

Как разрешить FilterableProductTable ререндеринг во время смены реквизита?

Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Навигация по приложениям React: Исчерпывающее руководство по React Router
Навигация по приложениям React: Исчерпывающее руководство по React Router
React Router стала незаменимой библиотекой для создания одностраничных приложений с навигацией в React. В этой статье блога мы подробно рассмотрим...
Массив зависимостей в React
Массив зависимостей в React
Все о массиве Dependency и его связи с useEffect.
0
0
33
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Ответ принят как подходящий

Когда вы устанавливаете состояние в функциональном компоненте, реакция выполняет === между старым и новым состоянием. Если они совпадают, то реакция пропускает рендеринг. Поскольку вы изменяете состояние, это один и тот же массив до и после, а рендеринг пропускается.

Исправление состоит в том, чтобы сохранить ваше состояние неизменным. Не изменяйте старый массив, а вместо этого создайте новый:

const handleClick = () => {
  changeProducts(prev => {
    const next = [...prev];
    next[0] = {
      ...next[0],
      category: 'haha';
    }
    return next;
  });
}

при изменении свойства в массиве реакция не видит его как изменение, вы можете использовать оператор распространения для клонирования вашего массива и установки нового массива:

changeProduct([...PRODUCTS])

разветвленные кодыибокс

useState вызовет повторный рендеринг, только если его текущее значение отличается от текущего состояния. Это сделает Object.is или === сравнение. Здесь вы устанавливаете ту же ссылку PRODUCTS, что и в defaultState, и значение, переданное в changeProduct, также имеет ту же ссылку, что и PRODUCTS, что не вызовет повторного рендеринга.

Цитата из React ДОКУМЕНТЫ

If your update function returns the exact same value as the current state, the subsequent rerender will be skipped completely.

const handleClick = () => {
  const res = productData.map((prod,index) => index === 0 ? {...prod,category:"haha"} : prod)
  changeProduct(res);
  console.info(res);
};

map каждый раз будет создавать новый массив.

Другие вопросы по теме