С redux вам на самом деле не нужно делить ваши данные назад и вперед между компонентами.
Если вы хотите, чтобы определенные данные были доступны для нескольких разбросанных компонентов, вы можете отправить некоторые действие (скажем, LIKE
увеличение like count
в глобальном состоянии) из компонента source (с помощью useDispatch()
) и извлечение необходимых данных (like count
) из хранилища, где бы они ни находились вам это нужно (используя useSelector()
):
//dependencies
const { useState } = React,
{ render } = ReactDOM,
{ createStore } = Redux,
{ useSelector, useDispatch, Provider } = ReactRedux
//mock source images pool
const images = {
tiger: 'https://i.dailymail.co.uk/1s/2019/10/29/14/20320992-7625529-Cara_a_five_year_old_125lb_Bengal_tiger_has_been_fitted_with_a_g-a-8_1572358357911.jpg',
tan: 'https://www.bioexpedition.com/wp-content/uploads/2013/05/Orangutan_close_up.jpg',
giraffe: 'https://img.thedailybeast.com/image/upload/c_crop,d_placeholder_euli9k,h_1440,w_2561,x_0,y_0/dpr_1.5/c_limit,w_1044/fl_lossy,q_auto/v1494008886/articles/2017/04/03/the-internet-s-most-famous-pregnant-giraffe-still-hasn-t-given-birth/170403-jones-pregnant-giraffe-tease_alsbhr'
}
//default state, action, reducer, store
const defaultState = {likes:{}},
LIKE = 'LIKE',
appReducer = (state=defaultState, action) => {
switch(action.type) {
case LIKE: {
const {payload: imgKey} = action,
{likes} = state
return {...state, likes:{...likes, [imgKey]: (likes[imgKey]||0)+1}}
}
default: return state
}
},
store = createStore(appReducer)
//Image component
const Image = ({imgSrc, imgKey}) => {
const dispatch = useDispatch(),
onLikeHit = imageKey => dispatch({type:LIKE, payload: imageKey})
return (
<div>
<img src={imgSrc} imageKey={imgKey} />
<div className="likebtn" onClick={() => onLikeHit(imgKey)}/>
</div>
)
}
//Image gallery
const ImageGallery = ({images}) => (
<div>
{Object.entries(images).map(([imgKey,imgSrc],key) => <Image {...{imgKey, imgSrc, key}} />)}
</div>
)
//Likes summary:
const Likes = () => {
const likes = useSelector(({likes}) => likes)
return (
<div>
{Object.entries(likes).map(([photo,count]) => <div>{photo}:{count}</div>)}
</div>
)
}
//entire App
render (
<Provider {...{store}}>
<ImageGallery {...{images}} />
<Likes />
</Provider>,
document.getElementById('root')
)
img {
max-width: 150px;
}
.likebtn {
width:30px;
height:30px;
background-image: url(data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMTAwIDEwMCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cGF0aCBkPSJNMTAgMzBhMjAgMjAgMCAwMTQwIDAgMjAgMjAgMCAwMTQwIDBxMCAzMC00MCA2MC00MC0zMC00MC02MHoiIGZpbGw9InJlZCIvPjwvc3ZnPg==)
}
.likebtn:hover {
cursor: pointer;
}
<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>