Using React 15.6.1 I'm making a QA forum and here's the code for rendering a single answer with multiple replies:
import React, { Component } from 'react';
import bindHelper from '../util/bindHelper';
const AnswerStub = (props) => (
<div className={props.wrapperClass}>
<div dangerouslySetInnerHTML={{ __html: props.answer.body }} />
<div className="pull-right">
<span>{props.answer.author.name}</span><br />
<span>{props.answer.postDate}</span>
</div>
</div>
)
class Answer extends Component {
constructor(props) {
super(props);
this.state = {
key: props.answer._id,
replyTo: false,
replyText: ''
}
bindHelper(this);
}
_handleReply(event) {
event.preventDefault();
console.log(event.target.id);
console.log(this.state.key);
this.setState({ replyTo: !this.state.replyTo });
}
_handleClear(event) {
this.setState({ replyText: '' });
}
_handleReplyChange(event) {
this.setState({ replyText: event.target.value });
}
_handlePostReply(event) {
//TODO: dispatch event handler for reply
}
render() {
return (
<div className="row answer">
<div className="col-md-1">
<span className={this.props.answer.accepted ? "glyphicon glyphicon-ok" : ""} />
</div>
<AnswerStub wrapperClass="col-md-11" answer={this.props.answer} />
<div className="comments col-md-12">
{this.props.answer.replies && this.props.answer.replies.map((reply, i) => <AnswerStub key={i} wrapperClass="comment-single" answer={reply} />)}
</div>
<div className="clearfix" />
{/* REPLY OPTION */}
<div className="col-md-offset-1 col-md-11">
<a id={`reply_${this.state.key}`} href="" onClick={this.handleReply.bind(this)}>
{this.state.replyTo ? "Cancel" : "Post a Reply"}
</a>
{this.state.replyTo &&
<div>
<textarea className="col-md-11 form-control" rows="3"
value={this.state.replyText} onChange={this.handleReplyChange} />
<br />
<button className="col-md-2 btn btn-default" onClick={this.handleClear}>Clear</button>
<button className="col-md-2 btn btn-primary pull-right" onClick={this.handlePostReply}>Post</button>
</div>
}
</div>
<div className="clearfix" />
<br />
</div>
);
}
}
export default Answer;
I am calling this in another component like
{this.props.answers && this.props.answers.map((ans,i) => <Answer key={ans._id} answer={ans} />)}
But when i click on a reply, the reply textbox for that opens, for every other case the last textbox keeps getting toggled no matter which link I click.
Sample output on the console:
59ba431d518a97998d310bd9
reply_59bba3b82219703fb84d07e7
59bba3b82219703fb84d07e7
reply_59ba431d518a97998d310bd9
59bba3b82219703fb84d07e7
reply_59bba3b82219703fb84d07e7
59bba3b82219703fb84d07e7
The target element is correct, but it's accessing the wrong state.
Shouldn't the states of each of the Answer component be separate? I cant figure out what is going on. And yes, I'm a beginner in React!
EDIT
bindHelper is a helper function i wrote to bind the this reference.
onClick={this.handleReply.bind(this)}at some point. Shouldn't it beonClick={this.handleReply}since you are handling the binding in the constructor?