reactjsfirebasequillrte

Comment reply system with React Quill and Firebase Firestore


I'm making a comment system with React Quill as my editor and Firebase Firestore. Each comment post gets stored in firestore. Each stored comment has a reply button, and when clicked, the editor should be populated with the comment content I want to reply to. Basically I need to populate my editor with the content stored in firestore database. Here's a screenshot as to watch I want to achieve:

Comment reply

Here's some code from the comment editor component

class NewComment extends Component {
constructor(props) {
super(props);

this.state = {
  comment: {
    commentID: "",
    content: "",
    createDate: new Date(),
    featureImage: "",
    isPublish: "True",
    createUserID: "",
  },
};
}
 ...
onChangeCommentContent = (value) => {
 this.setState({
  comment: {
    ...this.state.comment,
    content: value,
  },
});
};
...
render() {
 return (
  <Container>
    <Row>
      <Col xl={9} lg={8} md={8} sn={12}>
        <h2 className={classes.SectionTitle}>Comment</h2>

        <FormGroup>
          <ReactQuill
            ref={(el) => (this.quill = el)}
            value={this.state.comment.content}
            onChange={(e) => this.onChangeCommentContent(e)}
            theme="snow"
            modules={this.modules}
            formats={this.formats}
            placeholder={"Enter your comment"}
          />
        </FormGroup>
      </Col>...

The reply button is in a different component where I render the stored comments. Tell me if you need the full code from the components.


Solution

  • Here is a simple example on how to pass on information between two components via the parent component using function components:

    // Index.js
    const MyComponent = () => {
      const [replyValue, setReplyValue] = useState("");
    
      const onClick = (value) => {
        setReplyValue(value);
      };
    
      return (
        <>
          <Comment value="This is a reply" onClick={onClick} />
          <Comment value="This is another reply" onClick={onClick} />
          <CreateReply quoteValue={replyValue} />
        </>
      );
    };
    
    // Comment.js
    export const Comment = ({ value, onClick }) => {
      return (
        <div className="comment" onClick={() => onClick(value)}>
          {value}
        </div>
      );
    };
    
    // CreateReply.js
    export const CreateReply = ({ quoteValue = "" }) => {
      const [value, setValue] = useState("");
    
      useEffect(() => {
        setValue(quoteValue);
      }, [quoteValue]);
    
      const onValueUpdated = (newValue) => {
        if (newValue !== value) {
          setValue(newValue);
        }
      };
    
      return (
        <>
          <ReactQuill value={value} onChange={onValueUpdated} />
        </>
      );
    };
    

    Here is the same example using class components:

    // Index.js
    class MyComponent extends React.Component {
      constructor(props) {
        super(props);
    
        this.onClick = this.onClick.bind(this);
    
        this.state = {
          replyValue: ""
        };
      }
    
      onClick = (value) => {
        this.setState({
          replyValue: value
        });
      };
    
      render() {
        return (
          <>
            <Comment value="This is a reply" onClick={this.onClick} />
            <Comment value="This is another reply" onClick={this.onClick} />
            <CreateReply quoteValue={this.state.replyValue} />
          </>
        );
      }
    }
    
    // Comment.js
    export class Comment extends React.Component {
      render() {
        return (
          <div
            className="comment"
            onClick={() => this.props.onClick(this.props.value)}
          >
            {this.props.value}
          </div>
        );
      }
    }
    
    // CreateReply.js
    export class CreateReply extends React.Component {
      constructor(props) {
        super(props);
    
        this.onValueUpdated = this.onValueUpdated.bind(this);
    
        this.state = {
          value: props.quoteValue
        };
      }
    
      componentDidUpdate(prevProps) {
        if (this.props.quoteValue !== prevProps.quoteValue) {
          this.setState({
            value: this.props.quoteValue
          });
        }
      }
    
      onValueUpdated = (newValue) => {
        if (newValue !== this.state.value) {
          this.setState({
            value: newValue
          });
        }
      };
    
      render() {
        return (
          <>
            <ReactQuill value={this.state.value} onChange={this.onValueUpdated} />
          </>
        );
      }
    }