【问题标题】:Rendering data that being passed from parent component to a modal children on react渲染从父组件传递到模态子组件的数据反应
【发布时间】:2021-06-14 05:20:51
【问题描述】:

我有一个从我的 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

【问题讨论】:

  • 能否提供API结果?
  • 是的,我已经编辑过了。

标签: javascript reactjs react-hooks


【解决方案1】:

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

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>
  );
};

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

【讨论】:

  • 您好,感谢您的回复!但我认为这不是我的问题所在。在这里,我发布了一个关于它的 gif,以便更清楚:imgur.com/a/u9gvzFr
  • 在那些 gif 中,它显示即使我在项目 1 上单击了编辑,模式也会弹出包含来自最新项目(在本例中为项目 2)的值
【解决方案2】:

试试这个方法,

更新本地状态中选定的记录信息并将该信息传递给模型。

import React, { useState } from "react";
import "bootstrap/dist/css/bootstrap.min.css";
import { Modal, Button } from "react-bootstrap";

const data = [
  {
    id: 1001,
    firstname: "Mark",
    lastname: "Otto",
    age: 34,
    location: "London",
    address: "10 Downing Street"
  },
  {
    id: 1002,
    firstname: "Jacob",
    lastname: "Snow",
    age: 34,
    location: "India",
    address: "#110 broad Street"
  },
  {
    id: 1003,
    firstname: "Sarun",
    lastname: "U K",
    age: 30,
    location: "USA",
    address: "#1 NY"
  }
];

function App() {
  const [show, setShow] = useState(false);
  const [selectedData, setSelectedData] = useState({});
  const hanldeClick = (selectedRec) => {
    setSelectedData(selectedRec);
    setShow(true);
  };

  const hideModal = () => {
    setShow(false);
  };

  return (
    <div className="App">
      <table class="table">
        <thead>
          <tr>
            <th scope="col">Id</th>
            <th scope="col">First</th>
            <th scope="col">Last</th>
            <th scope="col">Location</th>
            <th scope="col">Show More</th>
          </tr>
        </thead>
        <tbody>
          {data.map((v) => (
            <tr>
              <td>{v.id}</td>
              <td>{v.firstname}</td>
              <td>{v.lastname}</td>
              <td>@{v.location}</td>
              <td>
                <a href="#" onClick={() => hanldeClick(v)}>
                  More details
                </a>
              </td>
            </tr>
          ))}
        </tbody>
      </table>
      <Dialog show={show} details={selectedData} handleClose={hideModal} />
    </div>
  );
}

const Dialog = ({ show, handleClose, details }) => {
  return (
    <Modal show={show} onHide={handleClose}>
      <Modal.Header closeButton>
        <Modal.Title>
          {details?.firstname} {details?.lastname}
        </Modal.Title>
      </Modal.Header>
      <Modal.Body>
        <table class="table">
          <thead>
            <tr>
              <th scope="col">Id</th>
              <th scope="col">First</th>
              <th scope="col">Last</th>
              <th scope="col">Age</th>
              <th scope="col">Location</th>
              <th scope="col">Address</th>
            </tr>
          </thead>
          <tbody>
            <tr>
              <td>{details?.id}</td>
              <td>{details?.firstname}</td>
              <td>{details?.lastname}</td>
              <td>{details?.age}</td>
              <td>{details?.location}</td>
              <td>{details?.address}</td>
            </tr>
          </tbody>
        </table>
      </Modal.Body>
      <Modal.Footer>
        <Button variant="secondary" onClick={handleClose}>
          Close
        </Button>
        <Button variant="primary" onClick={handleClose}>
          Save Changes
        </Button>
      </Modal.Footer>
    </Modal>
  );
};

export default App;

示例代码框 - https://codesandbox.io/s/react-model-dialog-box-askavy-forked-7uf94?file=/src/App.js:0-2922

【讨论】:

    猜你喜欢
    • 2023-04-03
    • 1970-01-01
    • 1970-01-01
    • 2021-12-24
    • 1970-01-01
    • 2020-03-04
    • 2020-11-21
    • 1970-01-01
    • 2021-01-23
    相关资源
    最近更新 更多