Yêu cầu thg 7 2, 2021 11:37 SA 71 0 1
  • 71 0 1
0

Popover re-render không thể lấy dc id đã click

Chia sẻ
  • 71 0 1

Mình có component Table mình map 1 cục xuống với mong muốn với Popup nào được Edit thì trả về ID để thằng cha Component Main xử lý Đây là Table

  <tbody>
        {debtsList.map((debt) => (
          <tr key={debt.id}>
            <td>{debt.id}</td>
            <td>{debt.name}</td>
            <td>{toCurrencyVND(toNumber(debt.borrowMoney))}</td>
            <td>{debt.interestPercent}%</td>
            <td>{formatDate(debt.startDate)}</td>
            <td>{formatDate(debt.endDate)}</td>
            <td>{toCurrencyVND(debt.liabilities)}</td>
            <td>
              <Popup
                key={debt.id}
                debt={debt}
                onEditClick={onDebtEditClick}
                onRemoveClick={onDebtRemoveClick}
                className="btn"
              />
            </td>
          </tr>
        ))}

Đây là Popup trong cái Popup có 2 cái button là edit và remove

 <>
      <button
        id="PopoverClick"
        type="button"
        className="popup__btn popup__btn-open "
        onClick={handleClick}
      >
        <svg
          xmlns="http://www.w3.org/2000/svg"
          className="icon icon-tabler icon-tabler-dots"
          width={30}
          height={30}
          viewBox="0 0 24 24"
          strokeWidth="1.5"
          stroke="currentColor"
          fill="none"
          strokeLinecap="round"
          strokeLinejoin="round"
        >
          <path stroke="none" d="M0 0h24v24H0z" fill="none" />
          <circle cx={5} cy={12} r={1} />
          <circle cx={12} cy={12} r={1} />
          <circle cx={19} cy={12} r={1} />
        </svg>
      </button>
      <Popover
        placement="right"
        isOpen={popoverOpen}
        target="PopoverClick"
        toggle={toggle}
      >
        <PopoverBody>
          <div className="popup__inner">
            <button
              className="popup__btn popup__btn-edit"
              onClick={handleEditClick}
            >
              <svg
                height={21}
                viewBox="0 0 21 21"
                width={21}
                xmlns="http://www.w3.org/2000/svg"
                className="popup__icon popup__icon-edit"
              >
                <g
                  fill="none"
                  fillRule="evenodd"
                  stroke="currentColor"
                  strokeLinecap="round"
                  strokeLinejoin="round"
                  transform="translate(3 3)"
                >
                  <path d="m14 1c.8284271.82842712.8284271 2.17157288 0 3l-9.5 9.5-4 1 1-3.9436508 9.5038371-9.55252193c.7829896-.78700064 2.0312313-.82943964 2.864366-.12506788z" />
                  <path d="m12.5 3.5 1 1" />
                </g>
              </svg>
              <span>Edit</span>
            </button>
            <button
              className="popup__btn popup__btn-remove"
              onClick={handleRemoveClick}
            >
              <svg
                className="popup__icon popup__icon-remove"
                height={21}
                width={21}
                xmlns="http://www.w3.org/2000/svg"
                fill="none"
                viewBox="0 0 24 24"
                stroke="currentColor"
              >
                <path
                  strokeLinecap="round"
                  strokeLinejoin="round"
                  strokeWidth={2}
                  d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16"
                />
              </svg>

              <span>Delete</span>
            </button>
          </div>
        </PopoverBody>
      </Popover>
    </>

Đấy phần handle của Popup

 const [popoverOpen, setPopoverOpen] = useState(false);
  const toggle = () => {
    setPopoverOpen(!popoverOpen);
  };

  console.log("render");
  const { debt, onEditClick, onRemoveClick } = props;

  const handleClick = () => {
    console.log(debt.id);
    //Đã log ra ID đã được Click
  };

  console.log(debt.id);
  const handleEditClick = () => {
    console.log(debt.id);
    if (onEditClick) {
    }
  };

  const handleRemoveClick = () => {
    if (onRemoveClick) {
      // onRemoveClick(debtId);
    }
  };

image.png

Tuy nhiên trong cái handleEditClickhandleRemoveClick thì không nhận được Id Mình dùng cái useState để lưu cái Id ở handleClick vào state clicked thì khi mình click Button Popver thì nó lại re-render lại vì do state const [popoverOpen, setPopoverOpen] = useState(false); này thay đổi nên nó về giá trị inititalnull do mình xét lúc đầu

Mình thấy const [popoverOpen, setPopoverOpen] = useState(false); do thằng nào bị thay đổi nên mình tách nó ra 1 component riêng như này

function ShowPopup(props) {
  const [popoverOpen, setPopoverOpen] = useState(false);
  const toggle = () => {
    setPopoverOpen(!popoverOpen);
  };
  const { debt } = props;

  const [debtClicked, setDebtClicked] = useState();

  const handleClick = () => {
    console.log(debt);
    if (!popoverOpen) {
      // setDebtClicked(debt);
    }
  };

  return (
    <>
      <button
        id="PopoverClick"
        type="button"
        className="popup__btn popup__btn-open "
        onClick={handleClick}
      >
        <svg
          xmlns="http://www.w3.org/2000/svg"
          className="icon icon-tabler icon-tabler-dots"
          width={30}
          height={30}
          viewBox="0 0 24 24"
          strokeWidth="1.5"
          stroke="currentColor"
          fill="none"
          strokeLinecap="round"
          strokeLinejoin="round"
        >
          <path stroke="none" d="M0 0h24v24H0z" fill="none" />
          <circle cx={5} cy={12} r={1} />
          <circle cx={12} cy={12} r={1} />
          <circle cx={19} cy={12} r={1} />
        </svg>
      </button>
      <Popover
        placement="right"
        isOpen={popoverOpen}
        target="PopoverClick"
        toggle={toggle}
      >
        <PopoverBody>{props.children}</PopoverBody>
      </Popover>
    </>
  );
}

export default ShowPopup;

lúc đó thằng Popup sẽ như thế này

<ShowPopup debt={debt}>
      <div className="popup__inner">
        <button
          className="popup__btn popup__btn-edit"
          onClick={handleEditClick}
        >
          <svg
            height={21}
            viewBox="0 0 21 21"
            width={21}
            xmlns="http://www.w3.org/2000/svg"
            className="popup__icon popup__icon-edit"
          >
            <g
              fill="none"
              fillRule="evenodd"
              stroke="currentColor"
              strokeLinecap="round"
              strokeLinejoin="round"
              transform="translate(3 3)"
            >
              <path d="m14 1c.8284271.82842712.8284271 2.17157288 0 3l-9.5 9.5-4 1 1-3.9436508 9.5038371-9.55252193c.7829896-.78700064 2.0312313-.82943964 2.864366-.12506788z" />
              <path d="m12.5 3.5 1 1" />
            </g>
          </svg>
          <span>Edit</span>
        </button>

        <button
          className="popup__btn popup__btn-remove"
          onClick={handleRemoveClick}
        >
          <svg
            className="popup__icon popup__icon-remove"
            height={21}
            width={21}
            xmlns="http://www.w3.org/2000/svg"
            fill="none"
            viewBox="0 0 24 24"
            stroke="currentColor"
          >
            <path
              strokeLinecap="round"
              strokeLinejoin="round"
              strokeWidth={2}
              d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16"
            />
          </svg>

          <span>Delete</span>
        </button>
      </div>
    </ShowPopup>

Vẫn k thể nào lấy dc id khi click button Edit

Mọi người giúp mình với ạ, mình k biết nên làm thế nào để fix lỗi này, mình mới học react thôi ạ

1 CÂU TRẢ LỜI


Đã trả lời thg 7 4, 2021 10:45 SA
Đã được chấp nhận
0

Phàn bảng và popup bạn có thể sửa lại như này cho tối ưu code:

const ComponenA = () => {
   const [isPopupVisible, setPopupVisible] = useState(false);

   function handleOpenPopup(e) {
       const { id } = e.dataset; // id của item
   }

    return (
        <div>
           <TableData handleOpenPopup={handleOpenPopup} /> // Toàn bộ phận map để render ra bảng
           <PopupComponent /> // Chỉ duy nhất 1 pop-up component dùng chung cho toàn bộ các row trong bảng
        </div>
    )
}

Bên trong <TableData /> của bạn ở mỗi cái button bạn sửa thành:

<button onClick={handleOpenPopup} data-id={itemId}>
    // ...
</button>

itemId ở đây chính là id bạn muốn truyền vào và sử dụng ở popup

Chia sẻ
Avatar HungHocHoi @HungSmeb
thg 7 5, 2021 7:40 SA

camr onw ban bữa giờ mình bận chưa check tý mình implement lại xem mình mới nên code theo kiểu logic dễ hiểu còn tối ưu thì mình chưa biết 😛

Avatar HungHocHoi @HungSmeb
thg 7 6, 2021 2:26 SA

Bạn có thể vào xem rồi note lại cho mình được không ạ : https://codesandbox.io/s/sweet-currying-j8nlj?file=/src/components/Table/Table.jsx mình đọc qua vẫn chưa hiểu

thg 7 6, 2021 4:03 SA

@HungSmeb code của bạn bị lỗi ở trong component <Popup /> nhé. Cụ thể bạn để ý component của bạn có id của button là:

<>
    <button
        id="PopoverClick"
        type="button"
        className="popup__btn popup__btn-open "
   >

Đồng thời các cái <Popover /> cũng tương tự có id là PopoverClick. Khi bạn render bảng dưới dạng map như đang làm hiện tại nó sẽ tạo ra 3 component Popup giống hệt nhau dẫn đến khi bạn click thì nó sẽ chỉ nhận cái cuối cùng thôi do toàn bộ bị trùng phần id. Giải pháp ở đây rất đơn giản, bạn chỉ cần đổi cái id trong button và trong cả <Popover /> component về dạng id={popover_${debt.id}}

Avatar HungHocHoi @HungSmeb
thg 7 7, 2021 4:31 CH

@HuyDQ Cảm ơn bạn nha Lúc trước mình đọc docs của reactstap cũng tới đoạn này rồi mình cũng có truyền thứ id nhưng mà mình truyền sai hay sao y nó k work Sau lần hỏi này mình rút ra kinh nghiệm 😍

thg 7 8, 2021 3:36 SA
Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí