Я новичок в реакции, и я пытаюсь создать простое приложение для корзины покупок без использования компонентов класса, узнав о хуках.В моем компонентном приложении верхнего уровня я получаю список элементов через импортированный json, затем создаю состояние с помощью useState для списка элементов, а также создаю редуктор для добавления или удаления элементов из корзины, которая имеет свое собственное состояние.Каждое состояние передается в компонент, ItemList вместе с функцией для отправки изменения состояния корзины (SpeiseListe в коде) и Cart.ItemList отображает список элементов в отдельные компоненты Item, у которых есть кнопка, которая запускает указанную отправку, и состояние перехватывания корзины в компоненте верхнего уровня обновляется.Теперь проблема заключается в том, что все приложение перерисовывается, как и ItemList, при каждом действии с корзиной.Я хотел бы обновить только компонент корзины, но я не уверен в правильном подходе.
(https://i.imgur.com/N6pfjvu.png)
Я не уверен, какое решение или концепция дляРешение может быть. Я думал о создании состояний в ItemList (SpeiseListe) и Cart соответственно, но тогда компонент Item должен был бы связаться со своими родными братьями и сестрами, и это не должно быть верно?
Приложение
import React, {useState, useReducer} from 'react'
import styled from 'styled-components'
import './bootstrap.min.css'
import Speisen from './Speisen'
import Cart from './Cart'
import * as speisen from './speisen.json'
export default function App() {
const cartHandlerReducer = (cart, action) => {
switch (action.type) {
case 'ADD_TO_CART':
return cart.concat(action.cartItem)
case 'REMOVE_FROM_CART':
return cart.filter(item => item.speise.id !== action.cartItem.speise.id)
default:
return cart
}
}
const speisenNumbered = speisen.default.speisen.map((item, i) => ({...item, itemOrder: i + 1}))
const [cart, dispatch] = useReducer(cartHandlerReducer, [])
const [speiseListe, setSpeiseListe] = useState(speisenNumbered)
const cartHandler = (cartItem) => {
if (cart.find(item => item.speise.id === cartItem.speise.id)) {
dispatch({type: 'REMOVE_FROM_CART', cartItem})
} else {
dispatch({type: 'ADD_TO_CART', cartItem})
}
}
const MainContainer = styled.div.attrs({
className: 'container'
})``
const Row = styled.div.attrs({
className: 'row'
})``
return (
<MainContainer>
<Row>
<Speisen
speisen={speiseListe}
cartHandler={cartHandler}
/>
<Cart
cart={cart}
/>
</Row>
</MainContainer>
)
}
Компонент отдельного элемента
import React, {useState} from 'react'
import styled from 'styled-components'
function Button(props) {
return (
<button
onClick={props.onClick}
>
{props.added ?
'remove' :
'add'
}
</button>
)
}
const SpeiseContainer = styled.div.attrs({
className: 'row'
})`
margin-bottom: 60px;
`
const OrderCol = styled.div.attrs({
className: 'col-1'
})``
const NameCol = styled.div.attrs({
className: 'col'
})``
const PreisCol = styled.div.attrs({
className: 'col-2'
})`
text-align: right;
`
const ButtonCol = styled.div.attrs({
className: 'col-auto'
})``
export default function Speise (props) {
const {speise, accomps, cartHandler} = props
const [currentAccomp, setCurrentAccomp] = useState(accomps && accomps[0].id)
const changeCurrentAccomp = (event) => setCurrentAccomp(accomps[event.target.value].id)
const cartItemButton = () => {
cartHandler({speise, accomps, currentAccomp})
}
console.log(currentAccomp)
return (
<SpeiseContainer>
<OrderCol>
{speise.itemOrder}
</OrderCol>
<NameCol>
{speise.name}
{currentAccomp && (
accomps.length > 1 ? (
<select
onChange={changeCurrentAccomp}
>
{accomps.map((accomp, i) =>
<option
key={accomp.id}
value={i}
>
{accomp.name}
</option>
)}
</select>
):(
accomps[0].name
)
)}
</NameCol>
<PreisCol>
{speise.price}
</PreisCol>
<ButtonCol>
<Button onClick={cartItemButton} />
</ButtonCol>
</SpeiseContainer>
)
}
Я хотел бы реализовать управление состояниями с помощью хуков, которые позволяют добавлять элементы в корзину без повторного отображения самого списка элементов только потому, что оба состоянияуправляется в одном и том же компоненте или по другому понимает, как это сделать вообще.
Большое спасибо!