首页 > 解决方案 > 渲染从父组件传递到模态子组件的数据反应

问题描述

我有一个从我的 API 获得的对象数组,然后将它们作为表行显示给父组件,如下所示:

审查.js 在此处输入图像描述

每行都有自己的编辑按钮,当我单击时,它将弹出一个模式(不重定向到另一个页面),它将包含一些基于我单击的行的信息。下面是当我单击以“Mamang Racing”作为客户端名称的第四行时的示例。

reviewDetailModal .js

在此处输入图像描述

问题是,在子组件(模态组件)上,当我出于某种原因要编辑任何其他行时,它仍会向我显示最新数据(在本例中为第四行)。

代码如下所示:

审查.js

const Review = () => {
  const [showModal, setShowModal] = useState("close");
  const [review, setReview] = useState([]);

  const handleClose = () => setShowModal("close");
  const handleShowModalOne = () => setShowModal("modal-one");
  const handleShowModalTwo = () => setShowModal("modal-two");

  useEffect(() => {
    let isMounted = false;
    const FetchReview = async () => {
      await publicAxios
        .get("/api/review/")
        .then((result) => {
          setReview(result.data);
        })
        .catch((err) => console.log(err));
    };
    FetchReview();
    console.log(review);
    return () => {
      isMounted = true;
    };
  }, []);
  return (
    <Layout>
      <Container fluid style={{ overflowY: "auto", paddingTop: "10px" }}>
        <div className="d-flex flex-row-reverse">
          <Button
            variant="success"
            className="mb-2"
            onClick={handleShowModalOne}
          >
            <FaPlusCircle /> Add Testimonial
          </Button>
          <AddReviewModal isShow={showModal} isClose={handleClose} />
        </div>
        <Table striped bordered hover className="text-center">
          <thead>
            <tr>
              <th>Client</th>
              <th>Review</th>
              <th>Action</th>
            </tr>
          </thead>
          <tbody>
            {review.map((item) => (
              <tr key={item._id}>
                <td className="align-middle">{item.clientName}</td>
                <td className="align-middle">{item.projectName} </td>
                <td style={{ width: "200px" }} className="align-middle">
                  <Button variant="primary" className="m-1 ">
                    <FaEye />
                  </Button>
                  <Button
                    variant="warning"
                    className="m-1"
                    onClick={handleShowModalTwo}
                  >
                    <FaPenSquare />
                  </Button>
                  <ReviewDetailModal
                    data={item}
                    isShow={showModal}
                    isClose={handleClose}
                  />
                  <Button variant="danger" className="m-1">
                    <FaTrashAlt />
                  </Button>
                </td>
              </tr>
            ))}
          </tbody>
        </Table>
      </Container>
    </Layout>
  );
};

reviewDetailModal.js

const ReviewDetailModal = ({ data, isShow, isClose }) => {
  return (
    <Modal show={isShow === "modal-two"} onHide={isClose}>
      <Modal.Header>
        <Modal.Title>Edit Review</Modal.Title>
      </Modal.Header>
      <Modal.Body>
        <Form>
          <Form.Group controlId="form.InputName">
            <Form.Label>Your Name</Form.Label>
            <Form.Control
              type="text"
              placeholder="Nama Anda"
              defaultValue={data.clientName}
            />
          </Form.Group>
          <Form.Group controlId="form.InputName">
            <Form.Label>Project Name</Form.Label>
            <Form.Control
              type="text"
              placeholder="Nama Anda"
              defaultValue={data.projectName}
            />
          </Form.Group>
          <Form.Group controlId="form.Rating">
            <Form.Label>Tinggalkan Rating : </Form.Label>
            <Form.Control as="select" defaultValue={data.rating}>
              <option>1</option>
              <option>2</option>
              <option>3</option>
              <option>4</option>
              <option>5</option>
            </Form.Control>
          </Form.Group>
          <Form.Group controlId="form.TextArea">
            <Form.Label>Kalimat Review</Form.Label>
            <Form.Control
              as="textarea"
              rows={3}
              defaultValue={data.description}
            />
          </Form.Group>
          <Form.Group>
            <label>Foto Anda</label>
            <Form.File id="pictureFile" />
          </Form.Group>
        </Form>
      </Modal.Body>
      <Modal.Footer>
        <Button onClick={isClose}>Close</Button>
      </Modal.Footer>
    </Modal>
  );
};

API 结果,我的数据之一:

Array(4) [ {…}, {…}, {…}, {…} ]
0: Object { _id: "60c18f1de4579e22d0e636cb", clientName: "pak dwek", projectName: "Landing Page Pakdwek", … }
__v: 0
_id: "60c18f1de4579e22d0e636cb"
clientName: "pak dwek"
createdAt: "2021-06-10T04:03:41.594Z"
description: "Sangat Baik , pelayanan memuaskan"
photo: "img/pakdhe.jpg"
projectName: "Landing Page Pakdwek"
score: 5
updatedAt: "2021-06-10T04:03:41.594Z"
<prototype>: Object { … }
1: Object { _id: "60c34afac1bdda333840a1cb", clientName: "alex", projectName: "landing page alex", … }
__v: 0
_id: "60c34afac1bdda333840a1cb"
clientName: "alex"
createdAt: "2021-06-11T11:37:30.852Z"
description: "sangat baik"
photo: "https://res.cloudinary.com/rembux-developer/image/upload/v1623411449/review-photos/ipbqv8xxqfs45yx9s5kz.jpg"
projectName: "landing page alex"
rating: 4
updatedAt: "2021-06-11T11:37:30.852Z"
<prototype>: Object { … }
2: Object { _id: "60c34b7ec1bdda333840a1cc", clientName: "Suhardono", projectName: "Project Web APp", … }
__v: 0
_id: "60c34b7ec1bdda333840a1cc"
clientName: "Suhardono"
createdAt: "2021-06-11T11:39:42.456Z"
description: "buruk"
photo: "https://res.cloudinary.com/rembux-developer/image/upload/v1623411581/review-photos/hkxt98hm28sb6sgc3wao.jpg"
projectName: "Project Web APp"
rating: 2
updatedAt: "2021-06-11T11:39:42.456Z"
<prototype>: Object { … }
3: Object { _id: "60c6d7a5eca83317bc8d0c5c", clientName: "Mamang Racing", projectName: "Test Project", … }
__v: 0
_id: "60c6d7a5eca83317bc8d0c5c"
clientName: "Mamang Racing"
createdAt: "2021-06-14T04:14:29.910Z"
description: "Bagusssss"
photo: "https://res.cloudinary.com/rembux-developer/image/upload/v1623644068/review-photos/sdha9mu1r6a3jvjfbqpm.png"
projectName: "Test Project"
rating: 3
updatedAt: "2021-06-14T04:14:29.910Z"
<prototype>: Object { … }
length: 4

标签: javascriptreactjsreact-hooks

解决方案


您必须创建一个保存方法并通过该保存方法将模态数据传递给Review 组件

评论.js

const Review = () => {
  const [showModal, setShowModal] = useState("close");
  const [review, setReview] = useState([]);

  const handleClose = () => setShowModal("close");
  const handleShowModalOne = () => setShowModal("modal-one");
  const handleShowModalTwo = () => setShowModal("modal-two");

  useEffect(() => {
    let isMounted = false;
    const FetchReview = async () => {
      await publicAxios
        .get("/api/review/")
        .then((result) => {
          setReview(result.data);
        })
        .catch((err) => console.log(err));
    };
    FetchReview();
    console.log(review);
    return () => {
      isMounted = true;
    };
  }, []);

  const onChangeReview = (index, obj) => {
    setReview((prev) =>
      prev.map((item, i) => (i === index ? { ...item, ...obj } : item))
    );
  }; // Update the state using the modal submitted data

  return (
    <Layout>
      <Container fluid style={{ overflowY: "auto", paddingTop: "10px" }}>
        <div className="d-flex flex-row-reverse">
          <Button
            variant="success"
            className="mb-2"
            onClick={handleShowModalOne}
          >
            <FaPlusCircle /> Add Testimonial
          </Button>
          <AddReviewModal isShow={showModal} isClose={handleClose} />
        </div>
        <Table striped bordered hover className="text-center">
          <thead>
            <tr>
              <th>Client</th>
              <th>Review</th>
              <th>Action</th>
            </tr>
          </thead>
          <tbody>
            {review.map((item, index) => (
              <tr key={item._id}>
                <td className="align-middle">{item.clientName}</td>
                <td className="align-middle">{item.projectName} </td>
                <td style={{ width: "200px" }} className="align-middle">
                  <Button variant="primary" className="m-1 ">
                    <FaEye />
                  </Button>
                  <Button
                    variant="warning"
                    className="m-1"
                    onClick={handleShowModalTwo}
                  >
                    <FaPenSquare />
                  </Button>
                  <ReviewDetailModal
                    index={index} {/* Pass the index of the item */}
                    data={item}
                    isShow={showModal}
                    isClose={handleClose}
                    onChangeReview={onChangeReview} {/* Pass the handler as an prop */}
                  />
                  <Button variant="danger" className="m-1">
                    <FaTrashAlt />
                  </Button>
                </td>
              </tr>
            ))}
          </tbody>
        </Table>
      </Container>
    </Layout>
  );
};

reviewDetailModal.js

const ReviewDetailModal = ({
  index,
  data,
  isShow,
  isClose,
  onChangeReview
}) => {
  const name = useRef(null);
  const project = useRef(null);
  const rate = useRef(null);
  const review = useRef(null);
  const picture = useRef(null); // Creating references to Modal form fields

  const onSave = () => {
    onChangeReview(index, {
      clientName: name.current.value,
      projectName: project.current.value,
      score: rate.current.value,
      review: review.current.value, // review info not exist in API returned array
      photo: picture.current.value
    });
  }; // Model data save handler

  return (
    <Modal show={isShow === "modal-two"} onHide={isClose}>
      <Modal.Header>
        <Modal.Title>Edit Review</Modal.Title>
      </Modal.Header>
      <Modal.Body>
        <Form>
          <Form.Group controlId="form.InputName">
            <Form.Label>Your Name</Form.Label>
            <Form.Control
              type="text"
              placeholder="Nama Anda"
              defaultValue={data.clientName}
              ref={name} {/* Pass the references to the the form fields */}
            />
          </Form.Group>
          <Form.Group controlId="form.InputName">
            <Form.Label>Project Name</Form.Label>
            <Form.Control
              type="text"
              placeholder="Nama Anda"
              defaultValue={data.projectName}
              ref={project}
            />
          </Form.Group>
          <Form.Group controlId="form.Rating">
            <Form.Label>Tinggalkan Rating : </Form.Label>
            <Form.Control as="select" defaultValue={data.rating} ref={rate}>
              <option>1</option>
              <option>2</option>
              <option>3</option>
              <option>4</option>
              <option>5</option>
            </Form.Control>
          </Form.Group>
          <Form.Group controlId="form.TextArea">
            <Form.Label>Kalimat Review</Form.Label>
            <Form.Control
              as="textarea"
              rows={3}
              defaultValue={data.description}
              ref={review}
            />
          </Form.Group>
          <Form.Group>
            <label>Foto Anda</label>
            <Form.File id="pictureFile" ref={picture} />
          </Form.Group>
        </Form>
      </Modal.Body>
      <Modal.Footer>
        <Button onClick={onSave}>Save</Button>{" "}
        {/* Add the Save handler to onClick */}
        <Button onClick={isClose}>Close</Button>
      </Modal.Footer>
    </Modal>
  );
};

如果您需要进一步的支持,请告诉我。


推荐阅读