I have a react component that shows a list of user data and images built with antd on nextJs. The reactions does not function as expected, all reactions and cards get clicked all at once instead of individually. I want to get each reaction and card component to have its unique click instead of all at once. Here's also a link
import React from 'react';
import { Avatar, Card, Icon, List } from 'antd';
import { ICON_LIST, LIST_TEXTS, STYLES, USER_UPLOAD } from './constants';
const { AVATAR, CARD_CONTAINER, ICON, USER_LIST } = STYLES;
const { INNER, MORE, UPLOAD, VERTICAL } = LIST_TEXTS
class Home extends React.Component {
state = {
clicks: 0,
};
IncrementIconText = () => {
this.setState({ clicks: this.state.clicks + 1 });
}
render() {
const actions = ( ICON_LIST.map(({ type }) => (
<span>
<Icon key={type} type={type} onClick={this.IncrementIconText} style={ICON} />
{this.state.clicks}
</span>
)));
return (
<List
itemLayout={VERTICAL}
dataSource={USER_UPLOAD}
renderItem={item => (
<List.Item style={USER_LIST}>
<Card
actions={actions}
cover={<img alt={UPLOAD} src={item.image} />}
extra={<Icon type={MORE} />}
hoverable
title={<a><Avatar src={item.image} style={AVATAR} />{item.user}</a>}
type={INNER}
style={CARD_CONTAINER}
>
{item.story}
</Card>
</List.Item>
)}
/>
);
}
}
export default Home;
constants.js
export const ICON_LIST = [
{
key: "heart",
type: "heart",
},
{
key: "dislike",
type: "dislike",
},
{
key: "meh",
type: "meh",
},
]
export const LIST_TEXTS = {
INNER: "inner",
MORE: "more",
UPLOAD: "upload",
VERTICAL: "vertical",
};
export const STYLES = {
AVATAR: {
marginRight: 8
},
CARD_CONTAINER: {
width: "650px",
marginBottom: 50
},
ICON: {
marginRight: 8
},
USER_LIST: {
width: "100%",
display: "flex",
justifyContent: "center",
alignItems: "center"
},
};
export const USER_UPLOAD = [
{
image: "http://sugarweddings.com/files/styles/width-640/public/1.%20The%20Full%20Ankara%20Ball%20Wedding%20Gown%20@therealrhonkefella.PNG",
story: "Today's my birthday next week! What do you think?",
user: "Chioma",
},
{
image: "https://dailymedia.com.ng/wp-content/uploads/2018/10/7915550_img20181007141132_jpeg01c125e1588ffeee95a6f121c35cd378-1.jpg",
story: "Going for an event. Do you like my outfit",
user: "Simpcy",
},
{
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",
story: "Saturdays are for weddings. Yay or nay!",
user: "Angela",
},
]
答案 0 :(得分:0)
No matter which icon you click on, all you are doing is incrementing the state of "clicks" and applying that state to all of your icons. So that is the why the click count is the same across all of your icons on each click. There should be a different "clicks" state counter for each individual icon the user can click on.
答案 1 :(得分:0)
You almost are ready to get the task you just have to add counters for every icon to get state separate and call the state according to the type of icon, a tiny implementation could be:
import React from "react";
import { Avatar, Card, Icon, List } from "antd";
import { ICON_LIST, LIST_TEXTS, STYLES, USER_UPLOAD } from "./constants";
const { AVATAR, CARD_CONTAINER, ICON, USER_LIST } = STYLES;
const { INNER, MORE, UPLOAD, VERTICAL } = LIST_TEXTS;
class Home extends React.Component {
state = {
clicks: 0,
heartClicks: 0,
dislikeClicks: 0,
emojiClicks: 0
};
IncrementIconText = type => {
if (type === "heart") {
this.setState({ heartClicks: this.state.heartClicks + 1 });
} else if (type === "dislike") {
this.setState({ dislikeClicks: this.state.dislikeClicks + 1 });
} else if (type === "meh") {
this.setState({ emojiClicks: this.state.emojiClicks + 1 });
}
};
render() {
const actions = ICON_LIST.map(({ type }) => (
<span>
<Icon
key={type}
type={type}
onClick={() => this.IncrementIconText(type)}
style={ICON}
/>
{type === "heart"
? this.state.heartClicks
: type === "dislike"
? this.state.dislikeClicks
: this.state.emojiClicks}
</span>
));
return (
<List
itemLayout={VERTICAL}
dataSource={USER_UPLOAD}
renderItem={item => (
<List.Item style={USER_LIST}>
<Card
actions={actions}
cover={<img alt={UPLOAD} src={item.image} />}
extra={<Icon type={MORE} />}
hoverable
title={
<a>
<Avatar src={item.image} style={AVATAR} />
{item.user}
</a>
}
type={INNER}
style={CARD_CONTAINER}
>
{item.story}
</Card>
</List.Item>
)}
/>
);
}
}
export default Home;
答案 2 :(得分:0)
Right now you have a single piece of state (clicks
) that is put on each icon. This is the same piece of state and the same handler for every icon, on every card.
To get your desired functionality, you will need a different count for every icon.
Here is an example of how to do that (I forked your codesandbox): https://codesandbox.io/s/pyj2288l0
Also, for state updates that depend on previous state, you should use this.setState((prevState) => {...})
. This is because state change can be asynchronous and this.state
isn't guaranteed to be the one you expect. Here are the docs on why you need that: https://reactjs.org/docs/state-and-lifecycle.html#state-updates-may-be-asynchronous