我有一个组件,我正在使用redux管理状态,并使用新映射从redux存储访问该组件的数组数据。我需要能够使我的图标的值在单击时增加。我不确定如何使用我的反应值来完成这项工作并使用handleReactions
constants.js
/** @constant */
export const INITIAL_STATE = {
uploads: new Map(),
};
export const USER_UPLOADS = [
{
_id: 0,
image: 'http://sugarweddings.com/files/styles/width-640/public/1.%20The%20Full%20Ankara%20Ball%20Wedding%20Gown%20@therealrhonkefella.PNG',
reactions: {
dislike: 0,
like: 0,
maybe: 0,
},
story: "It's my birthday next week! What do you think?",
user: 'Chioma',
},
{
_id: 1,
image: 'https://dailymedia.com.ng/wp-content/uploads/2018/10/7915550_img20181007141132_jpeg01c125e1588ffeee95a6f121c35cd378-1.jpg',
reactions: {
dislike: 0,
like: 0,
maybe: 0,
},
story: 'Going for an event. Do you like my outfit?',
user: 'Simpcy',
},
{
_id: 2,
image: 'https://i0.wp.com/www.od9jastyles.com/wp-content/uploads/2018/01/ankara-styles-ankara-styles-gown-ankara-tops-ankara-gowns-ankara-styles-pictures-latest-ankara-style-2018-latest-ankara-styles-ankara-ankara-styles.png?fit=437%2C544&ssl=1',
reactions: {
dislike: 0,
like: 0,
maybe: 0,
},
story: 'Saturdays are for weddings. Yay or nay?',
user: 'Angela',
},
];
actions.js
import { UPDATE_REACTION, REQUEST_UPLOAD_LIST } from './actionTypes';
/**
* Triggers request to react on a post
*
* @function
* @return {Object} The {@link actionTypes.REQUEST_UPLOAD_LIST REQUEST_UPLOAD_LIST}
* action.
*/
export function updateReaction(itemid, reaction) {
return {
itemid,
reaction,
type: UPDATE_REACTION,
};
}
/**
* Triggers request for the lists of uploads
*
* @function
* @return {Object} The {@link actionTypes.REQUEST_UPLOAD_LIST REQUEST_UPLOAD_LIST}
* action.
*/
export const requestUploadList = payload => ({
payload,
type: REQUEST_UPLOAD_LIST,
});
reducers.js
import { UPDATE_REACTION, REQUEST_UPLOAD_LIST } from './actionTypes';
import { INITIAL_STATE, USER_UPLOADS } from './constants';
/**
* Creates a Javascript Map with the user uploads mapped by id
*
* @param {Array} USER_UPLOADS - a users uploads
* @return {Map} - the user uploads
*/
function generateUploadsMap() {
const setOfUserUploads = new Map();
USER_UPLOADS.forEach(userUpload => {
const { _id } = userUpload;
setOfUserUploads.set(_id, userUpload);
});
return setOfUserUploads;
}
function updateItemReactions(itemid, reaction, uploads) {
const upload = uploads.get(itemid);
upload.reactions = {
...upload.reactions,
[reaction]: upload.reactions[reaction] + 1,
};
uploads.set(itemid, upload);
return uploads;
}
console.log(updateItemReactions());
export default (state = { ...INITIAL_STATE }, action) => {
switch (action.type) {
case REQUEST_UPLOAD_LIST: {
return {
...state,
uploads: generateUploadsMap(),
};
}
case UPDATE_REACTION: {
const { uploads } = state;
return {
...state,
uploads: updateItemReactions(action.itemid, action.reaction, uploads),
};
}
default:
return state;
}
};
home.js
import PropTypes from 'prop-types';
import React from 'react';
import { Avatar, Card, Icon, List } from 'antd';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import { LIST_TEXTS, STYLES } from '../constants';
import * as actions from '../actions';
import { getUploads } from '../selectors';
const { AVATAR, CARD_CONTAINER, CARD_LIST, ICON, USER_LIST } = STYLES;
const { INNER, MORE, UPLOAD, VERTICAL } = LIST_TEXTS;
const IconText = ({ type, text }) => (
<span>
<Icon type={type} style={ICON} />
{text}
</span>
);
function createReactionsIcon(item, updateReaction) {
const { like, dislike, maybe } = item.reactions;
const icons = [
{ reaction: 'like', text: `${like}`, type: 'heart' },
{ reaction: 'dislike', text: `${dislike}`, type: 'dislike' },
{ reaction: 'maybe', text: `${maybe}`, type: 'meh' },
];
return icons.map(({ reaction, text, type }) => (
<IconText
onClick={updateReaction(item._id, reaction)}
key={reaction}
type={type}
text={text}
/>
));
}
class Home extends React.Component {
componentDidMount() {
const { requestUploadList } = this.props.actions;
requestUploadList();
}
updateReaction = (itemid, reaction) => {
const { updateReaction } = this.props.actions;
updateReaction(itemid, reaction);
}
render() {
const { uploads } = this.props;
const values = Array.from(uploads.values());
return (
<div style={CARD_CONTAINER}>
<List
itemLayout={VERTICAL}
dataSource={values}
renderItem={item => (
<List.Item style={USER_LIST}>
<Card
actions={createReactionsIcon(item, this.updateReaction)}
cover={<img alt={UPLOAD} src={item.image} />}
extra={<Icon type={MORE} />}
hoverable
title={(
<a href="/">
<Avatar src={item.image} style={AVATAR} />
{item.user}
</a>
)}
type={INNER}
style={CARD_LIST}
>
{item.story}
</Card>
</List.Item>
)}
/>
</div>
);
}
}
Home.propTypes = {
uploads: PropTypes.instanceOf(Map),
actions: PropTypes.object,
};
const mapStateToProps = state => ({
uploads: getUploads(state),
});
const mapDispatchToProps = dispatch => ({
actions: bindActionCreators(actions, dispatch),
});
export default connect(mapStateToProps, mapDispatchToProps)(Home);
答案 0 :(得分:1)
在mapDispatchToProps
中,您绑定了动作创建者,并设置了在actions
组件中传递的Home
道具的。
在Icon
中生成的createReactionsIcon
元素不知道一种处理onClick
事件的方法,而不是不提供一种向redux-store
分发动作以进行更新的方法反应。
在Home
中,actions.updateReactions
需要转发到createReactionsIcon
,并为其onClick
的{{1}}事件注册。
IconText
在
render() {
//...
<Card
actions={createReactionsIcon(item, this.props.actions.updateReaction)}
//...
}
中,
createReactionsIcon
在这里,
function createReactionsIcon(item, updateReaction) {
const { like, dislike, maybe } = item.reactions;
const icons = [
{ reaction: 'like', text: `${like}`, type: 'heart'},
{ reaction: 'dislike', text: `${dislike}`, type: 'dislike'},
{ reaction: 'maybe', text: `${maybe}`, type: 'meh'},
];
//...
return icons.map(({ reaction, text, type }) => (
<IconText
onClick={() => updateReaction(item._id, reaction)}
key={reaction}
type={type}
text={text}
/>
));
}
中updateReaction
动作创建者的定义应被修改为包括更多字段,例如动作的项目和反应。
actions.js
然后使function updateReaction(itemid, reaction) {
return {
type: UPDATE_REACTION,
itemid,
reaction
}
}
动作类型的化简器使用它来更新UPDATE_REACTION
中项ID的反应。
reducer.js
其中///...
case UPDATE_REACTION:
const { uploads } = state;
return {
...state,
uploads: updateItemReaction(action.itemid, action.reaction, uploads),
};
}
///...
是定义为的函数:
updateItemReaction
现在,虽然上面的方法可以让您看到存储中的对象是
function updateItemReaction(itemid, reaction, uploads) { const upload = uploads.get(itemid) const uploadUpdate = { ...upload, reactions: { ...upload.reactions, [reaction]: upload.reactions[reaction] + 1 } } uploads.set(itemid, uploadUpdate) return uploads; }
。 必须注意仅更新已更改部分的存储,以便仅重新渲染使用该部分中的值的组件。我强烈建议考虑为组件状态使用不可变的数据结构,或通过使用普通对象严格将存储区视为不可变的。