Почему мой компонент реакции не выполняет рендеринг после отправки действия, которое изменяет хранилище избыточности? - PullRequest
0 голосов
/ 22 июня 2019

Я просто играю с Redux, извините за любые ошибки или плохие практики.

У меня в основном есть список компьютерных частей, которые пользователь может выбрать / отменить выбор.Каждая часть представляет собой объект JS, который имеет идентификатор, имя, цену и выбранное поле:

const initialState = {
    products: [
        {product_id: 0, product_name: "Hard Drive 320 GB 5400 RPM", price: 1450, selected: false},
        {product_id: 1, product_name: "Solid State Drive 128 GB R/W - 420 MB/s", price: 1880, selected: false},
        {product_id: 2, product_name: "Gigabyte MB A270S AM4 DDR4 3200HZ OC HDMI/VGA/DVI", price: 3560, selected: false},
        {product_id: 3, product_name: "Asus MB A420M LGA 1151 3200HZ OC HDMI/VGA", price: 3660, selected: false},
        {product_id: 4, product_name: "nVidia GTX 1050 Ti 4GB GDDR5 VRAM", price: 13450, selected: false},
        {product_id: 5, product_name: "Intel i5 7200 kabylake CPU 3.6 GHz 4 cores 4 threads", price: 9800, selected: false},
        {product_id: 6, product_name: "AMD Ryzed 5 2600G CPU 3.2 GHz 4 cores 4 threads", price: 9380, selected: false},
        {product_id: 7, product_name: "8 GB Hyper-X DDR4 RAM memory 3200 MHz CL15", price: 3450, selected: false},
        {product_id: 8, product_name: "450W Sharkoon PSU 80 plus black semi modular", price: 2250, selected: false},
        {product_id: 9, product_name: "ATX Case w/ Acrilyc Glass panel & LED Strips", price: 1720, selected: false},
    ],
    sum: 0
}

(это просто практика, поэтому я не загружаю данные из остальных API или любого другого)

Затем я подписываюсь на хранилище приставок с моим компонентом приложения, используя функцию connect, и передаю функции mapStateToProps и mapDispatchToProps:

function mapStateToProps(state){
    return {
        products: state.products,
        sum: state.sum
    }
}

function mapDispatchToProps(dispatch){
    return {
        toggle: (product_id) => dispatch(ACTIONS.toggle(product_id))
    }
}


export default connect(mapStateToProps, mapDispatchToProps)(App)

Затем внутри компонента приложения я создаю константный массив длякоторый я сопоставляю все продукты и генерирую возврат JSX для div с содержимым внутри него, и к каждому div я добавляю linstener события (onClick), который запускает диспетчер this.props.toggle:

const products = this.props.products.map(product => {
    return (
        <div className="product" key={product.product_id} onClick={ () => {this.props.toggle(product.product_id) }}>
            <h2>{product.product_name}</h2>
            {product.selected ? ('') : (<h3>{product.price}</h3>)}
        </div>
    )
})

И когда действие отправляется, это происходит в редукторе:

switch(action.type){
    case ACTION_TYPES.PRODUCT_TOGGLE:
        const newState = state
        newState.products[action.payload].selected = !newState.products[action.payload].selected
        if(newState.products[action.payload].selected === true){
            newState.sum = newState.sum + newState.products[action.payload].price
        } else {
            newState.sum = newState.sum - newState.products[action.payload].price
        }
        console.log(newState.sum)
        return newState
    default:
        return state
}

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

Ответы [ 2 ]

2 голосов
/ 22 июня 2019

Вы изменяете объект state, newState и state - это одна и та же ссылка на объект, поэтому UI не обновляется.

Вы должны вернуть новый объект из редуктора.

Создайте новый объект перед тем, как поменять объект таким образом

const newState = { ...state }
1 голос
/ 22 июня 2019

Когда вы запускаете newState = state, вы просто создаете переменную, которая ссылается на тот же объект, что и ваше старое состояние, поэтому, когда вы присваиваете новые значения этому объекту, вы изменяете старый объект.

Redux и React-Redux используют строгие проверки на равенство, чтобы определить, было ли обновлено ваше состояние.Поскольку ссылки на объекты совпадают, он считает, что состояние не изменилось.

const oldState = { a: 1 };
const newState = oldState;
newState.a = 2;
console.log(oldState);
console.log(newState);
console.log(oldState === newState);

См. Эту статью на предмет неизменности: https://redux.js.org/faq/immutable-data#why-is-immutability-required-by-redux

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...