我正在映射一个div,所以它会根据我数据库中的数据量进行渲染。在我的情况下,我的div渲染了4次。 (这是一项有4个选项的民意调查。)
我会逐步解释我的问题。
1)我想设置div的背景颜色,与我得到的id相匹配 从页面加载时的数据库。我这样做了
componentDidMount() {
let sel3 = document.getElementById(this.props.voted_id);
if (sel3) {
sel3.style.backgroundColor = "#0b97c4";
sel3.style.color = "#FFFFFF";
}
}
这里this.props.voted_id
是我从数据库中获取的id。 (这是用户选择的轮询选项的ID。所以在componentDidMount上我通过设置背景颜色来显示所选选项)
2)如果用户想要更改他/她的选择,用户可以通过单击新选项进行更改。我想将背景颜色设置为所选的新选择用户,同时我想删除先前所选选项的背景颜色。 我这样做是
我的组件
render() {
let {contents, submitvote, postId, voted_id} = this.props
return (
<div className="txt_vote_bar_div" id={this.props.contents.post_poll_content_id}>
<p className="txt_vote_choice" id={this.props.contents.post_poll_content_id}
onClick={() => {
this.handleClick(this.props.contents.post_poll_content_id);
}}>
{contents.content}
</p>
<p className="txt_tot_votes"> {this.props.contents.votes_percentage}%
({this.state.voteCount} Votes)</p>
</div>
);
};
在handleClick函数上,我正在执行以下操作
handleClick(id) {
let sel = document.getElementById(this.props.voted_id);
if (sel) {
alert("1");
sel.style.backgroundColor = "#FFFFFF";
sel.style.color = "#6a6a6a";
}
let sel2 = document.getElementById(this.props.getVoteStatus);
if (sel2) {
alert("2");
sel2.style.backgroundColor = "#FFFFFF";
sel2.style.color = "#6a6a6a";
}
let el = document.getElementById(id);
if (el) {
alert("3");
this.setState({
active: false,
})
el.style.backgroundColor = "#0b97c4";
el.style.color = "#FFFFFF";
}
let sel3 = document.getElementById(id);
if (sel3.id == this.props.getVoteStatus && this.state.active == false) {
alert("4");
this.setState({
active: true,
})
sel3.style.backgroundColor = "#FFFFFF";
sel3.style.color = "#6a6a6a";
}
}
此处this.props.voted_id
是我从数据库中获取的ID(我使用此ID在componentDidMount
上设置背景)
此处this.props.getVoteStatus
是我之前选择的ID选项,用于在用户选择新选项时删除背景颜色。
到目前为止,我成功地做到了这一点,没有任何问题。但我的问题是这个
当页面加载并且如果我从数据库中获取id时,具有id的特定div被着色。那没关系。但是当用户选择相同的选择(撤回他/她的选择)时
这段代码按原样运行(因为用户选择的div id与我从数据库中获取的id相同)
let sel = document.getElementById(this.props.voted_id);
if (sel) {
alert("2");
sel.style.backgroundColor = "#FFFFFF";
sel.style.color = "#6a6a6a";
}
然后这段代码运行
let el = document.getElementById(id);
if (el) {
alert("1");
this.setState({
active: false,
})
el.style.backgroundColor = "#0b97c4";
el.style.color = "#FFFFFF";
}
此问题仅在页面加载后出现一次。在那种情况下,两部分代码都是有效的。因此它运行两者。我该如何解决这个问题?
更新
这就是我如何映射我的div元素
export const TextVoteList = ({postData, submitvote}) => {
const dataUnavailable = (
<div>
<p>
There are no voting options available available
</p>
</div>
);
const dataAvailable = (
<div>
{postData.post_poll_content.map(contents => <TextVoteOptions key={contents.post_poll_content_id} voted_id={postData.personal_vote} contents={contents} submitvote = {submitvote} postId = {postData._id}/>)}
</div>
);
return (
<div>
{postData.post_poll_content.length === 0 ? dataUnavailable : dataAvailable}
</div>
);
};
TextVoteOptions 代码
render() {
alert(this.props.getVoteResponse);
let {contents, submitvote, postId, voted_id} = this.props
return (
<div key={this.props.contents.post_poll_content_id} className= {(this.state.voted_id === this.props.contents.post_poll_content_id && this.state.active) ? "txt_vote_bar_div active" : "txt_vote_bar_div"}>
<p className="txt_vote_choice" id={this.props.contents.post_poll_content_id}
onClick={() => {
this.handleClick(this.props.contents.post_poll_content_id);
}}>
{contents.content}
</p>
<p className="txt_tot_votes"> {this.props.contents.votes_percentage}%
({this.state.voteCount} Votes)</p>
</div>
);
};
我的点击处理程序
handleClick(id) {
let vote_object = {
voting_object: id,
post_id: this.props.postId
}
this.setState({
voted_id: id,
active: (id != this.state.voted_id) ? true : !this.state.active
});
this.props.submitvote(vote_object);
}
答案 0 :(得分:1)
你应该自己避免实际的DOM操作。让React处理实际的DOM操作。据我了解,我的设计如下。请尝试和关联。希望这会有所帮助。
在你的问题中,我不明白状态'active'的用法,所以我没有在下面的代码片段中使用过。这是你想要实现的目标。
const contents = [
{
post_poll_content_id: 1,
content: "Soccer",
votes_percentage: 60
},
{
post_poll_content_id: 2,
content: "Cricket",
votes_percentage: 20
},
{
post_poll_content_id: 3,
content: "Basketball",
votes_percentage: 20
}
];
const votedId = 3; // Assume this is coming from database;
class Demo extends React.Component {
constructor(props) {
super(props);
this.state = {
voteCount: 100,
voted_id: props.voted_id,
active:true
};
this.handleClick = this.handleClick.bind(this);
}
handleClick(id) {
this.setState({
voted_id: id,
active: (id != this.state.voted_id) ? true : !this.state.active
});
}
render() {
let {contents, voted_id} = this.props;
return (
<div>
{contents.map((content, index) => {
return (
<div key={index} className= {(this.state.voted_id===content.post_poll_content_id && this.state.active) ? "txt_vote_bar_div active" : "txt_vote_bar_div"}
id={content.post_poll_content_id}
>
<p
className="txt_vote_choice"
id={content.post_poll_content_id}
onClick={() => {
this.handleClick(content.post_poll_content_id);
}}
>
{content.content}
</p>
<p className="txt_tot_votes">
{content.votes_percentage % this.state.voteCount} Votes
</p>
</div>
);
})}
</div>
);
}
}
ReactDOM.render(<Demo contents={contents} voted_id = {votedId}/>, document.getElementById("app"));
.txt_vote_bar_div {
display:block;
border:1px solid #eee;
margin: 10px;
width:20%;
text-align:center;
}
.active {
background-color:#0b97c4;
color:#FFF;
}
.txt_vote_choice {
color:'blue';
cursor:pointer;
text-decoration:underline;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="app"></div>