Adding Child (Comment) part to every Parent (Answer) Component in React.js

Viewed 41
import React, { useState, useEffect } from 'react'
import { Link } from 'react-router-dom'
import moment from 'moment'
import Avatar from '../../components/Avatar/Avatar'
import { useSelector, useDispatch} from 'react-redux'
import { useParams } from 'react-router-dom'
import { deleteAnswer } from '../../actions/question'

const DisplayAnswer = ( { question, handleShare }  ) => {

    const User = useSelector((state) => (state.currentUserReducer))
    const dispatch = useDispatch()
    const { id } = useParams()
    
    const [button, setButton] = useState(false);

    const handleDelete = (answerId, noOfAnswers) => {
        dispatch(deleteAnswer(id, answerId, noOfAnswers-1))
    }

    const handleComment = (e) => {
        setButton(!button)
        alert(e.target.id)
    }

    return (
        <div>
            {   
                question.answer.map( (ans) => (
                    <div className="display-ans" key={ans._id}>
                        <p>{ans.answerBody}</p>
                        <div className="question-actions-user">
                            <div>
                                <button type="button" onClick={handleShare}>Share</button>
                                {          
                                    User?.result?._id === ans?.userId && (
                                        <button type='button' onClick={ () => handleDelete(ans._id, question.noOfAnswers) }>Delete</button>
                                    )
                                }

                                <div>
                                        
                                </div>

                                <button id = {ans._id} type='button' onClick = { (e) => handleComment(e) }> Add Comment </button>

                                {
                                    button && 
                                    (
                                        <div id = {ans._id}>
                                            <textarea rows='5' cols='30'> </textarea> <br />
                                            <button type='button'> Post </button>
                                        </div>
                                    )
                                }
                                
                            </div>

                            <div>
                                <p>answered { moment(ans.answeredOn).fromNow()}</p>
                                <Link to={`/Users/${ans.userId}`} className='user-link' style={{color:'#0086d8'}}>
                                    <Avatar backgroundColor="lightgreen" px='8px' py='5px' borderRadius='4px'>{ans.userAnswered.charAt(0).toUpperCase()}</Avatar>
                                    <div>
                                        {ans.userAnswered}
                                    </div>
                                </Link>
                            </div>

                        </div>

                   </div> 

                ))
            }
        </div>


    )
}

export default DisplayAnswer

I want to add a comment part under every answer to do that i added a " Add Comment " button under every Answer and i have a button click on that button

and what i want is whenever the button is clicked the addcomment (textbox) should be added under it

but when i click the button the addcomment (textbox) is getting added under every answer

like if 10 answers are their then Addcommment box is getting added under every 10 answers

2 Answers

Each answer must have his own 'state' to display his own textArea, so you have to extract the code of the 'answer' in a new Answer component, and render a new component in the map method.

Each Answer will thus use a "useState" with a "[isTextAreaVisible, setIsTextAreaVisible] = useState(false);" state.

Currently there is only a single button state that all the mapped answers render a button for. A simple solution would be to instead store the answer id of the answer you want to add a comment for.

Example:

const DisplayAnswer = ({ question, handleShare }) => {
  ...

  const [commentId, setCommentId] = useState(null); // <-- initially null

  ...

  const handleComment = (e) => {
    setCommentId(e.target.id); // <-- set answer id here
    alert(e.target.id);
  };

  return (
    <div>
      {question.answer.map((ans) => (
        <div className="display-ans" key={ans._id}>
          <p>{ans.answerBody}</p>
          <div className="question-actions-user">
            <div>
              ...

              <button
                id={ans._id}
                type="button"
                onClick={handleComment}
              >
                Add Comment
              </button>

              {commentId === and._id && ( // <-- conditionally render match by id
                <div id={ans._id}>
                  <textarea rows="5" cols="30" />
                  <br />
                  <button type="button">Post</button>
                </div>
              )}
            </div>

            ...
          </div>
        </div>
      ))}
    </div>
  );
};

When the "Post comment" button is clicked and the entered comment is handled don't forget to also set the commentId value back to null to conditionally hide the input.

Related