#reactjs #redux
Вопрос:
поэтому я пытаюсь отправить несколько объектов, а затем отобразить их. Проблема в том, что вместо добавления нового объекта в массив я перезаписываю их, и он меняется на новый. Итак, у меня есть несколько продуктов, которые являются отдельными объектами. Я помещаю их в массив и отправляю массив сюда:
function Product({ id, title, image, price, rating }) { const [items, setItems] = useState([]); const dispatch = useDispatch(); useEffect(() => { dispatch( pushItems({ items, }) ); console.log(items); }, [items]); return ( <div className="product"> <div className="product__Info"> <p>{title}</p> <p className="product__Info__price"> <small>
lt;/small>
<strong>{price}</strong>
</p>
<div className="product__Info__rating">
{Array(rating)
.fill()
.map((_, i) => (
<p>⭐</p>
))}
</div>
</div>
<img src={image} alt="" />
<button
onClick={(e) =>
setItems({
title,
image,
price,
rating,
})
}
>
Add to basket
</button>
</div>
);
}
и вот как выглядит мой редуктор, в котором, я думаю, проблема:import { createSlice } from "@reduxjs/toolkit"; const checkoutSlice = createSlice({ name: "checkout", initialState: { items: null, }, reducers: { pushItems: (state, action) => { state.items = [...state.items, action.payload.items]; }, }, }); export const { pushItems } = checkoutSlice.actions; export const selectItems = (state) => state.checkout.items; export default checkoutSlice.reducer;
Я знаю, как это сделать «по-старому», но когда я использую срезы, я немного сбит с толку.
Ответ №1:
Вашему компоненту продукта не нужно хранить массив элементов, вы можете напрямую обновить массив элементов в магазине redux
function Product({ id, title, image, price, rating }) { const dispatch = useDispatch(); const onAddItem = (item) => { dispatch(pushItems({item})); } return ( <div className="product"> <div className="product__Info"> <p>{title}</p> <p className="product__Info__price"> <small>
lt;/small>
<strong>{price}</strong>
</p>
<div className="product__Info__rating">
{Array(rating)
.fill()
.map((_, i) => (
<p>⭐</p>
))}
</div>
</div>
<img src={image} alt="" />
<button
onClick={(e) =>
onAddItem({
title,
image,
price,
rating,
})
}
>
Add to basket
</button>
</div>
);
}
Также обратите внимание, что обновление состояния внутриredux-toolkit
среза не должно заботиться о неизменности, поскольку оно используется внутриimmer
.Вы можете обновить свое состояние восстановления, как показано ниже:
const checkoutSlice = createSlice({ name: "checkout", initialState: { items: null, }, reducers: { pushItems: (state, action) => { state.items.push(action.payload.item); }, }, });
Комментарии:
1. Я предполагаю, что ваш способ похож на мой, поэтому, когда я пытаюсь сделать это таким образом:
pushItems: (state, action) => { state.items = action.payload.items;
, это перезаписывает мое состояние.2. нажатие отличается от прямой замены. Как я уже упоминал, вам нужно использовать
state.items.push(action.payload.item)
Также обратите внимание, что я также изменил внутренний код продукта3. Я пытался сделать это, как ты сказал, и я получаю
Actions may not have an undefined "type" property. Have you misspelled a constant?
, Когда я пытаюсьdispatch(pushItems({item)})
, я получаюCannot read property 'push' of null
4. О, и в исходном состоянии должен быть массив { items: [] } вместо { items: null } @larryfisherman, который исправит вашу ошибку
5. @LindaPaiste Спасибо, что указал на это. Я обновил свой ответ.