Với DOM element thì gần như không. Tạo một closure là thao tác rất rẻ, và React gắn listener theo cơ chế delegation nên không phải add/remove listener mỗi lần render.
Vấn đề chỉ xuất hiện khi hàm đó là prop của một component đã bọc memo: mỗi lần render cha sinh ra một tham chiếu hàm mới, so sánh nông thấy khác → memo mất tác dụng hoàn toàn.
const Row = memo(function Row({ onSelect }) { /* ... */ })
// new function identity on every parent render → Row always re-renders
<Row onSelect={() => select(id)} />Cùng logic đó áp cho object/array literal: style={{ margin: 8 }}, items={[]}, config={{ ...opts }} đều tạo tham chiếu mới mỗi lần.
Cách xử lý theo thứ tự:
1. Không bọc memo nếu chưa đo được lợi ích — thì inline function hoàn toàn ổn.
2. Nếu thật sự cần memo, giữ tham chiếu ổn định bằng useCallback/useMemo, hoặc đưa dữ liệu tĩnh ra ngoài component (const EMPTY = []).
3. Hoặc đổi thiết kế prop: truyền id xuống và cho con tự gọi onSelect(id) — hàm không cần đóng gói theo item nữa.