Reactjs 在react中使用map函数时,如何仅传递相关道具?

Reactjs 在react中使用map函数时,如何仅传递相关道具?,reactjs,react-props,map-function,Reactjs,React Props,Map Function,我有一个ReviewList组件,它通过数据库映射,并用评论列表填充页面。在每个评论中,我还传递一个编辑模式组件,在其中我尝试传递道具。我面临的问题是,试图只通过与具体审查相适应的道具。相反,它传递映射的每个审阅的道具,因此当尝试在编辑模式组件中编辑审阅时,它总是修改第一个审阅,因为它是道具列表中的第一个审阅。例如,当I console.log _idprop时,我会收到映射的每个评论的_id,而不仅仅是单击编辑按钮的特定评论的_id 审阅列表组件: import { Link } from '

我有一个ReviewList组件,它通过数据库映射,并用评论列表填充页面。在每个评论中,我还传递一个编辑模式组件,在其中我尝试传递道具。我面临的问题是,试图只通过与具体审查相适应的道具。相反,它传递映射的每个审阅的道具,因此当尝试在编辑模式组件中编辑审阅时,它总是修改第一个审阅,因为它是道具列表中的第一个审阅。例如,当I console.log _idprop时,我会收到映射的每个评论的_id,而不仅仅是单击编辑按钮的特定评论的_id

审阅列表组件:

import { Link } from 'react-router-dom';
import { Modal, Button } from "react-bootstrap";
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import Edit from "../Edit/index";
import Auth from "../../utils/auth";

const ReviewList = ({ reviews, profileReviewEdit }) => {
  const [showEditModal, setShowEditModal] = useState(false);

  const reload = () => window.location.reload();

  if (!reviews.length) {
    return (
      <h1 className='pageText'>No Reviews Yet</h1>
    )
  }

  return (
    <>
      <div className="containter center">

        {reviews && reviews.map((review) => (
          
          <div className='row bloc-box'>

            <div className='col-3'>
              <Link to={`/gamepage/${review.gameId}`}>
                <img src={`${review.gameCoverUrl}`}
                  fluid
                  thumbnail
                  width={200}
                />
              </Link>


              <Link to={`/gamepage/${review.gameId}`}>
                <h5 className='game-title'>{review.gameTitle}</h5>
              </Link>

            </div>

            <div className='col'>

              <h3 className='col'>
                <p className='review-title'>{review.title}</p>
              </h3>


              <div className="pl-3">
                <p className="username-link">
                  Written by: <Link
                    to={`/profile/${review.username}`}
                    style={{ fontWeight: 700 }}>
                    {review.username}
                  </Link>{' '} on {review.createdAt}
                </p>
              </div>

              <div>
                <div className="col-9">
                  <h4 className='review-text'>{review.reviewBody}</h4>
                </div>
              </div>

              <div className='col-9'>

                {[...Array(parseInt(`${review.rating}`))].map((star, i) => {
                  const ratingValue = i + 1;

                  return (
                    <label>
                      <input
                        type='radio'
                        name='rating'
                        value={review.rating}
                      />
                      <FontAwesomeIcon className='star'
                        icon='star'
                        size='lg'
                        color={review.rating ? '#ffc107' : '#e4e5e9'}
                      />
                    </label>

                  )
                })}
              </div>
              <p className='small-title'> {review.rating}/5 Stars </p>

            </div>

            <div>
              {Auth.loggedIn(), profileReviewEdit &&
                <div>
                  <Button variant="outline-warning" size='sm' onClick={() => setShowEditModal(true)}>
                    <FontAwesomeIcon icon="edit" color="#FEBE10" size="lg" />Edit</Button>{' '}
                </div>}
            </div>



            <div >

              <Modal
                size="lg"
                show={showEditModal}
                onHide={() => setShowEditModal(false)}
                onExit={reload}
              >
                <Modal.Header closeButton>
                  <Modal.Title>Edit Review</Modal.Title>
                </Modal.Header>
                <Modal.Body>
                  <Edit
                    handleModalClose={() => setShowEditModal(false)}
                    _id={review._id}
                    reviewTitle={review.title}
                    reviewBody={review.reviewBody}
                    setShowEditModal={setShowEditModal}
                  />
                </Modal.Body>
              </Modal>
            </div>

          </div>

        ))}

      </div>

    </>
  )
};

export default ReviewList;
import { useMutation } from "@apollo/react-hooks";
import { EDIT_REVIEW, DELETE_REVIEW } from "../../utils/mutations";
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';

const Edit = ({ _id, reviewTitle, reviewBody, setShowEditModal }) => {
  console.log(_id);
  const [ editReview ] = useMutation(EDIT_REVIEW);
  const [ deleteReview ] = useMutation(DELETE_REVIEW);

  const [title, setTitle] = useState("");
  const [titleCharacterCount, setTitleCharacterCount] = useState(0);

  const [editBody, setEditBody] = useState("");
  const [editBodyCharacterCount, SetEditBodyCharacterCount] = useState(0);
  console.log(editBody);

  const [rating, setRating] = useState(null);
  const [hover, setHover] = useState(null);

  console.log()

  const handleTitleChange = (event) => {
    if (event.target.value.length <= 30) {
      setTitle(event.target.value);
      setTitleCharacterCount(event.target.value.length);
    }
  };

  const handleEditBodyChange = (event) => {
    if (event.target.value.length <= 1000) {
      setEditBody(event.target.value);
      SetEditBodyCharacterCount(event.target.value.length);
    }
  };

  const handleFormSubmit = async (event) => {
    event.preventDefault();
    // reviewBody = editBody;

    try {
      await editReview({
        variables: { _id:_id, title:title, reviewBody:editBody, rating:rating },
      });

      // clear form value
      setTitle("");
      setTitleCharacterCount(0);
      setEditBody("");
      SetEditBodyCharacterCount(0);
      setShowEditModal(false);
    } catch (e) {
      console.error(e);
    }
  };

  const handleDelete = async ( _id ) => {
    console.log(_id)
    try {
      await deleteReview({
        variables: { _id },
      });
      setShowEditModal(false);
    } catch (e) {
      console.error(e);
    }
  }

  const StarRating = () => {
    return (
      <div>
        {[...Array(5)].map((star, i) => {
          const ratingValue = i + 1;

          return (
            <label>
              <input 
                type='radio' 
                name='rating' 
                value={ratingValue} 
                onClick={() => setRating(ratingValue)}
              />
              <FontAwesomeIcon className='star'
                icon='star'
                size='2x'
                color= {ratingValue <= (hover || rating) ? '#ffc107' : '#e4e5e9'}
                onMouseEnter={() => setHover(ratingValue)}
                onMouseLeave={() => setHover(null)}
              />
            </label>
          )
        })}
        <h5> {rating}/5 Stars </h5>
      </div>
    )
  }

  return (
    <div>
      <form
        className="flex-row justify-center justify-space-between-md align-stretch"
        onSubmit={handleFormSubmit}
      >
        <textarea
          placeholder={reviewTitle}
          value={title}
          className="form-input col-12 col-md-9"
          onChange={handleTitleChange}
        ></textarea>
        <p className={`m-0 ${titleCharacterCount === 30 ? "text-error" : ""}`}>
          Character Count: {titleCharacterCount}/30
        </p>

        <textarea
          placeholder={reviewBody}
          value={editBody}
          className="form-input col-12 col-md-9"
          onChange={handleEditBodyChange}
        ></textarea>
        <p
          className={`m-0 ${editBodyCharacterCount === 1000 ? "text-error" : ""
            }`}
        >
          Character Count: {editBodyCharacterCount}/1000
        </p>
        <StarRating />

        {/* {error && <span className="ml-2">Something went wrong...</span>} */}
        <button className="btn btn-success col-12 col-md-3" type="submit">
          Submit
        </button>
      </form>
      <button className="btn btn-danger mt-1 col-12 col-md-3" type="button" onClick={() => handleDelete(_id)}>
        Delete Review
      </button>
    </div>
  );
}

export default Edit;
从'react router dom'导入{Link};
从“react bootstrap”导入{Modal,Button};
从'@fortawesome/react fontawesome'导入{FontAwesomeIcon};
从“./编辑/索引”导入编辑;
从“../../utils/Auth”导入授权;
const ReviewList=({reviews,profileReviewEdit})=>{
const[showEditModal,setShowEditModal]=useState(false);
const reload=()=>window.location.reload();
如果(!reviews.length){
返回(
还没有评论
)
}
返回(
{reviews&&reviews.map((review)=>(
{review.gameTitle}

{review.title}

作者: {review.username} {review.createdAt}上的{'}

{review.reviewBody} {[…数组(parseInt(`${review.rating}')].map((星形,i)=>{ 常数值=i+1; 返回( ) })}

{review.rating}/5星

{Auth.loggedIn(),profileReviewEdit&& setShowEditModal(真)}> 编辑{'} } setShowEditModal(假)} onExit={reload} > 编辑评论 setShowEditModal(假)} _id={review.\u id} reviewTitle={review.title} reviewBody={review.reviewBody} setShowEditModal={setShowEditModal} /> ))} ) }; 导出默认审阅列表;
编辑组件:

import { Link } from 'react-router-dom';
import { Modal, Button } from "react-bootstrap";
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import Edit from "../Edit/index";
import Auth from "../../utils/auth";

const ReviewList = ({ reviews, profileReviewEdit }) => {
  const [showEditModal, setShowEditModal] = useState(false);

  const reload = () => window.location.reload();

  if (!reviews.length) {
    return (
      <h1 className='pageText'>No Reviews Yet</h1>
    )
  }

  return (
    <>
      <div className="containter center">

        {reviews && reviews.map((review) => (
          
          <div className='row bloc-box'>

            <div className='col-3'>
              <Link to={`/gamepage/${review.gameId}`}>
                <img src={`${review.gameCoverUrl}`}
                  fluid
                  thumbnail
                  width={200}
                />
              </Link>


              <Link to={`/gamepage/${review.gameId}`}>
                <h5 className='game-title'>{review.gameTitle}</h5>
              </Link>

            </div>

            <div className='col'>

              <h3 className='col'>
                <p className='review-title'>{review.title}</p>
              </h3>


              <div className="pl-3">
                <p className="username-link">
                  Written by: <Link
                    to={`/profile/${review.username}`}
                    style={{ fontWeight: 700 }}>
                    {review.username}
                  </Link>{' '} on {review.createdAt}
                </p>
              </div>

              <div>
                <div className="col-9">
                  <h4 className='review-text'>{review.reviewBody}</h4>
                </div>
              </div>

              <div className='col-9'>

                {[...Array(parseInt(`${review.rating}`))].map((star, i) => {
                  const ratingValue = i + 1;

                  return (
                    <label>
                      <input
                        type='radio'
                        name='rating'
                        value={review.rating}
                      />
                      <FontAwesomeIcon className='star'
                        icon='star'
                        size='lg'
                        color={review.rating ? '#ffc107' : '#e4e5e9'}
                      />
                    </label>

                  )
                })}
              </div>
              <p className='small-title'> {review.rating}/5 Stars </p>

            </div>

            <div>
              {Auth.loggedIn(), profileReviewEdit &&
                <div>
                  <Button variant="outline-warning" size='sm' onClick={() => setShowEditModal(true)}>
                    <FontAwesomeIcon icon="edit" color="#FEBE10" size="lg" />Edit</Button>{' '}
                </div>}
            </div>



            <div >

              <Modal
                size="lg"
                show={showEditModal}
                onHide={() => setShowEditModal(false)}
                onExit={reload}
              >
                <Modal.Header closeButton>
                  <Modal.Title>Edit Review</Modal.Title>
                </Modal.Header>
                <Modal.Body>
                  <Edit
                    handleModalClose={() => setShowEditModal(false)}
                    _id={review._id}
                    reviewTitle={review.title}
                    reviewBody={review.reviewBody}
                    setShowEditModal={setShowEditModal}
                  />
                </Modal.Body>
              </Modal>
            </div>

          </div>

        ))}

      </div>

    </>
  )
};

export default ReviewList;
import { useMutation } from "@apollo/react-hooks";
import { EDIT_REVIEW, DELETE_REVIEW } from "../../utils/mutations";
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';

const Edit = ({ _id, reviewTitle, reviewBody, setShowEditModal }) => {
  console.log(_id);
  const [ editReview ] = useMutation(EDIT_REVIEW);
  const [ deleteReview ] = useMutation(DELETE_REVIEW);

  const [title, setTitle] = useState("");
  const [titleCharacterCount, setTitleCharacterCount] = useState(0);

  const [editBody, setEditBody] = useState("");
  const [editBodyCharacterCount, SetEditBodyCharacterCount] = useState(0);
  console.log(editBody);

  const [rating, setRating] = useState(null);
  const [hover, setHover] = useState(null);

  console.log()

  const handleTitleChange = (event) => {
    if (event.target.value.length <= 30) {
      setTitle(event.target.value);
      setTitleCharacterCount(event.target.value.length);
    }
  };

  const handleEditBodyChange = (event) => {
    if (event.target.value.length <= 1000) {
      setEditBody(event.target.value);
      SetEditBodyCharacterCount(event.target.value.length);
    }
  };

  const handleFormSubmit = async (event) => {
    event.preventDefault();
    // reviewBody = editBody;

    try {
      await editReview({
        variables: { _id:_id, title:title, reviewBody:editBody, rating:rating },
      });

      // clear form value
      setTitle("");
      setTitleCharacterCount(0);
      setEditBody("");
      SetEditBodyCharacterCount(0);
      setShowEditModal(false);
    } catch (e) {
      console.error(e);
    }
  };

  const handleDelete = async ( _id ) => {
    console.log(_id)
    try {
      await deleteReview({
        variables: { _id },
      });
      setShowEditModal(false);
    } catch (e) {
      console.error(e);
    }
  }

  const StarRating = () => {
    return (
      <div>
        {[...Array(5)].map((star, i) => {
          const ratingValue = i + 1;

          return (
            <label>
              <input 
                type='radio' 
                name='rating' 
                value={ratingValue} 
                onClick={() => setRating(ratingValue)}
              />
              <FontAwesomeIcon className='star'
                icon='star'
                size='2x'
                color= {ratingValue <= (hover || rating) ? '#ffc107' : '#e4e5e9'}
                onMouseEnter={() => setHover(ratingValue)}
                onMouseLeave={() => setHover(null)}
              />
            </label>
          )
        })}
        <h5> {rating}/5 Stars </h5>
      </div>
    )
  }

  return (
    <div>
      <form
        className="flex-row justify-center justify-space-between-md align-stretch"
        onSubmit={handleFormSubmit}
      >
        <textarea
          placeholder={reviewTitle}
          value={title}
          className="form-input col-12 col-md-9"
          onChange={handleTitleChange}
        ></textarea>
        <p className={`m-0 ${titleCharacterCount === 30 ? "text-error" : ""}`}>
          Character Count: {titleCharacterCount}/30
        </p>

        <textarea
          placeholder={reviewBody}
          value={editBody}
          className="form-input col-12 col-md-9"
          onChange={handleEditBodyChange}
        ></textarea>
        <p
          className={`m-0 ${editBodyCharacterCount === 1000 ? "text-error" : ""
            }`}
        >
          Character Count: {editBodyCharacterCount}/1000
        </p>
        <StarRating />

        {/* {error && <span className="ml-2">Something went wrong...</span>} */}
        <button className="btn btn-success col-12 col-md-3" type="submit">
          Submit
        </button>
      </form>
      <button className="btn btn-danger mt-1 col-12 col-md-3" type="button" onClick={() => handleDelete(_id)}>
        Delete Review
      </button>
    </div>
  );
}

export default Edit;
从“@apollo/react hooks”导入{usespation}”;
从“./../utils/mutations”导入{EDIT_REVIEW,DELETE_REVIEW}”;
从'@fortawesome/react fontawesome'导入{FontAwesomeIcon};
常量编辑=({u id,reviewTitle,reviewBody,setShowEditModal})=>{
console.log(_id);
常量[editReview]=使用变异(编辑审查);
const[deleteReview]=使用变异(DELETE_REVIEW);
const[title,setTitle]=useState(“”);
常量[titleCharacterCount,setTitleCharacterCount]=useState(0);
const[editBody,setEditBody]=useState(“”);
常量[editBodyCharacterCount,SetEditBodyCharacterCount]=useState(0);
console.log(editBody);
const[rating,setRating]=useState(null);
const[hover,setHover]=useState(null);
console.log()
const handleitlechange=(事件)=>{
if(event.target.value.length{
if(event.target.value.length{
event.preventDefault();
//reviewBody=编辑主体;
试一试{
待审({
变量:{u id:{u id,title:title,reviewBody:editBody,rating:rating},
});
//清除形式值
片名(“”);
setTitleCharacterCount(0);
setEditBody(“”);
SetEditBodyCharacterCount(0);
设置ShowEditModal(假);
}捕获(e){
控制台错误(e);
}
};
const handleDelete=async(_id)=>{
console.log(_id)
试一试{
待审({
变量:{u id},
});
设置ShowEditModal(假);
}捕获(e){
控制台错误(e);
}
}
常数星号=()=>{
返回(
{[…数组(5)].map((星,i)=>{
常数值=i+1;
返回(
设定值(额定值)}
/>
setHover(null)}
/>
)
})}
{评级}/5星
)
}
返回(

字符计数:{titleCharacterCount}/30

字符计数:{editBodyCharacterCount}/1000

{/*{错误&&出了问题…}*/} 提交 handleDelete(_id)}> 删除评论 ); } 导出默认编辑;
整个问题的体系结构有点混乱。我正试图解决这个问题以及您提到的问题的体系结构。但始终尝试使您的组件更精确

首先

您不应为每个审阅呈现模式,而应创建单个模式,然后在编辑时单击“将审阅存储在状态中”,并将该审阅传递给模式

换个新钩子

const [currentReview, setCurrentReview] = useState(null);
其次

现在
Edit
按钮点击如下设置评论


    <Button variant="outline-warning" size='sm' onClick={() => setCurrentReview(review)}>
         <FontAwesomeIcon icon="edit" color="#FEBE10" size="lg" />Edit
    </Button>


设置