在 React 函数组件中的 onClick 事件中,我应该通过引用传递函数还是创建匿名函数?
On an onClick event in a React function component, should I pass a function by reference or make an anonymous function?
我发现了这个问题,但它没有回答我的具体情况,因为答案是旧的,不要在这个 post 中回答我的所有问题,在那种情况下,他们只会将事件变量传递给函数,但在我的例子中,我可能想传递不同类型的值,比如字符串:
在 React 中,在功能组件上,假设我有一个按钮:
return <button>Click me</button>
我想给它添加一个 onClick 事件,但我不想将鼠标事件传递给该函数,而是想发送其他类型的数据。 什么是正确的(或者更好,性能最好的)模式?
用例是一个包含数百个单元格的网格,每个单元格都有一个 onClick 事件。我想选项 b 会更好,因为我们只传递一个引用,对吧? 现代 React 是否针对此用例进行了某种优化?
一)
const handleClick = (value) => console.log(value);
return <button onClick={() => handleClick('hello')}>Click me</button>
b)
const handleClick = (value) => () => console.log(value);
return <button onClick={handleClick('hello')}>Click me</button>
b) 除非你的 handleClick
函数 returns 一个新函数(就像第一个例子一样)它不会工作因为你所做的只是赋值调用该函数的结果而不是引用函数。
a) 将 工作但是有很多文档表明在每个渲染器上重新绑定箭头函数会导致性能不佳。
我更喜欢 onClick={fn}
然后在组件内或组件外定义函数,或者我可能已经导入了它。无论哪种方式,我认为它使它更具可读性。但这是一种观点,许多开发人员有不同的方法。
但主要问题是:不要将点击监听器附加到每个单元格!这很可能 将 导致性能问题。相反:a) 将 one 侦听器添加到包含元素(例如 table
),然后使用 event delegation watch for events from the cells as the "bubble up" the DOM. b) Use Data attributes to attach specific data to the cells, and pick up their data in the click handler from the dataset.
所以:一个人为的例子来向您展示最后几点:
function Example() {
// Because we're using event delegation
// check to see if the element we clicked on
// was actually a table cell, then grab the id
// from its dataset
function handleClick(e) {
if (e.target.matches('td')) {
const { id } = e.target.dataset;
console.log(id);
}
}
// One listener to rule them all
return (
<table onClick={handleClick}>
<tbody>
<tr>
<td data-id="1">One</td>
<td data-id="2">Two</td>
<td data-id="3">Three</td>
</tr>
</tbody>
</table>
);
}
ReactDOM.render(
<Example />,
document.getElementById('react')
);
table { border: 1px solid #565656; border-collapse: collapse; }
td { border: 1px solid #787878; padding: 0.3em; }
td:hover { cursor: pointer; background-color: #dfdfdf; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js"></script>
<div id="react"></div>
我发现了这个问题,但它没有回答我的具体情况,因为答案是旧的,不要在这个 post 中回答我的所有问题,在那种情况下,他们只会将事件变量传递给函数,但在我的例子中,我可能想传递不同类型的值,比如字符串:
在 React 中,在功能组件上,假设我有一个按钮:
return <button>Click me</button>
我想给它添加一个 onClick 事件,但我不想将鼠标事件传递给该函数,而是想发送其他类型的数据。 什么是正确的(或者更好,性能最好的)模式?
用例是一个包含数百个单元格的网格,每个单元格都有一个 onClick 事件。我想选项 b 会更好,因为我们只传递一个引用,对吧? 现代 React 是否针对此用例进行了某种优化?
一)
const handleClick = (value) => console.log(value);
return <button onClick={() => handleClick('hello')}>Click me</button>
b)
const handleClick = (value) => () => console.log(value);
return <button onClick={handleClick('hello')}>Click me</button>
b) 除非你的
handleClick
函数 returns 一个新函数(就像第一个例子一样)它不会工作因为你所做的只是赋值调用该函数的结果而不是引用函数。a) 将 工作但是有很多文档表明在每个渲染器上重新绑定箭头函数会导致性能不佳。
我更喜欢
onClick={fn}
然后在组件内或组件外定义函数,或者我可能已经导入了它。无论哪种方式,我认为它使它更具可读性。但这是一种观点,许多开发人员有不同的方法。但主要问题是:不要将点击监听器附加到每个单元格!这很可能 将 导致性能问题。相反:a) 将 one 侦听器添加到包含元素(例如
table
),然后使用 event delegation watch for events from the cells as the "bubble up" the DOM. b) Use Data attributes to attach specific data to the cells, and pick up their data in the click handler from the dataset.
所以:一个人为的例子来向您展示最后几点:
function Example() {
// Because we're using event delegation
// check to see if the element we clicked on
// was actually a table cell, then grab the id
// from its dataset
function handleClick(e) {
if (e.target.matches('td')) {
const { id } = e.target.dataset;
console.log(id);
}
}
// One listener to rule them all
return (
<table onClick={handleClick}>
<tbody>
<tr>
<td data-id="1">One</td>
<td data-id="2">Two</td>
<td data-id="3">Three</td>
</tr>
</tbody>
</table>
);
}
ReactDOM.render(
<Example />,
document.getElementById('react')
);
table { border: 1px solid #565656; border-collapse: collapse; }
td { border: 1px solid #787878; padding: 0.3em; }
td:hover { cursor: pointer; background-color: #dfdfdf; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js"></script>
<div id="react"></div>