Я думаю, что это редуктор, который должен обрабатывать описанную логику c, а не создатель действий (?) addRecipient
.
Так что, как я понял, в обычном рабочем процессе Redux вам нужно изменить свойства глобального состояния recipient
(должен быть добавлен новый получатель) и recipientProduct
(должны добавляться элементы, соответствующие каждому продукту с количеством по умолчанию 1) при отправке действия APPEND_RECIPIENT
или такого.
Мое решение для этого было бы следующее:
appReducer = (state=initialState, action) => {
switch(action.type){
case 'APPEND_RECIPIENT' : {
let {payload: recipientId} = action,
{recipient:{allIds:recipientIds}, recipientProduct, product:{allIds:productIds}} = state
if(recipientIds.includes(recipientId)) return state
recipientIds = [...recipientIds, recipientId]
recipientProduct = [...recipientProduct,...productIds.map(productId => ({productId, recipientId, qty: '1'}))]
return {...state, recipient:{allIds:recipientIds}, recipientProduct}
}
default: return state
}
}
Ниже вы можете найти демонстрационную версию этой концепции:
//dependencies
const { useState } = React,
{ render } = ReactDOM,
{ createStore } = Redux,
{ connect, Provider } = ReactRedux
//initial state, reducer and store
const initialState = {product:{allIds:['1','5']},recipient:{allIds:['1']},recipientProduct:[{recipientId:'1',productId:'1',qty:'3'},{recipientId:'1',productId:'5',qty:'3'}]},
appReducer = (state=initialState, action) => {
switch(action.type){
case 'APPEND_RECIPIENT' : {
let {payload: recipientId} = action,
{recipient:{allIds:recipientIds}, recipientProduct, product:{allIds:productIds}} = state
if(recipientIds.includes(recipientId)) return state
recipientIds = [...recipientIds, recipientId]
recipientProduct = [...recipientProduct,...productIds.map(productId => ({productId, recipientId, qty: '1'}))]
return {...state, recipient:{allIds:recipientIds}, recipientProduct}
}
default: return state
}
},
store = createStore(appReducer)
//append recipient form ui component
const AppendRecipient = ({onAppendRecipient, onInput}) => {
const [inputValue, setInput] = useState()
return (
<form onSubmit={e => (e.preventDefault(), onAppendRecipient(inputValue))}>
<input type="number" onKeyUp={e => setInput(e.target.value)} />
<input type="submit" name="Append Recipient" />
</form>
)
}
//connect onAppendRecipient handler to dispatching 'APPEND_RECIPIENT' action
const mapDispatchToProps = dispatch => ({
onAppendRecipient: recipientId => dispatch({type:'APPEND_RECIPIENT', payload:recipientId})
}),
AppendRecipientContainer = connect(null, mapDispatchToProps)(AppendRecipient)
//mirroring recipientProducts
const RecipientProducts = ({products, productsQty}) => (
<div>
{
products.map(({recipientId,productId,qty},key) => <div {...{key}}>recipient:{recipientId}, product:{productId}, qty: {qty}</div>)
}
</div>
)
//connect output element to global recipientProducts
const mapStateToProps = ({recipientProduct}) => ({products:recipientProduct, productsQty:recipientProduct.length}),
RecipientProductsContainer = connect(mapStateToProps)(RecipientProducts)
//render the entire app
render (
<Provider store={store}>
<AppendRecipientContainer />
<RecipientProductsContainer />
</Provider>,
document.getElementById('root')
)
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.12.0/umd/react.production.min.js"></script><script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.11.0/umd/react-dom.production.min.js"></script><script src="https://cdnjs.cloudflare.com/ajax/libs/redux/4.0.5/redux.min.js"></script><script src="https://cdnjs.cloudflare.com/ajax/libs/react-redux/7.1.3/react-redux.min.js"></script><div id="root"></div>