Popover re-render không thể lấy dc id đã click
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);
}
};
Tuy nhiên trong cái handleEditClick
và handleRemoveClick
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ị initital
là null
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
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
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 😛
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
@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}
}
@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 😍