我有以下情况
export default class MyComponent extends Component {
myFunc = dynamicKey => {
// do something with the dynamic key
}
render() {
return (
<Foo>
<button onClick={e => this.myFunc(someDynamicKey1)} />
<button onClick={e => this.myFunc(someDynamicKey2)} />
<button onClick={e => this.myFunc(someDynamicKey3)} />
{/* ... */}
</Foo>
)
}
}
这是很常见的情况,但这不好,因为在每个渲染中它都创建那个箭头功能。
因此,作为一个解决方案,我制作了一个函数,该函数使用该键返回另一个函数。
export default class MyComponent extends Component {
myFunc = dynamicKey => e => {
// do something with the dynamic key
}
render() {
return (
<Foo>
<button onClick={this.myFunc(someDynamicKey1)} />
<button onClick={this.myFunc(someDynamicKey2)} />
<button onClick={this.myFunc(someDynamicKey3)} />
{/* ... */}
</Foo>
)
}
}
现在,我不在每个渲染上创建一个新函数,但在每个渲染上调用一个新函数。
现在我不确定要使用哪个。在每个函数上调用函数都是不好的做法吗?我应该使用箭头功能吗?
[使用curried function时,可以在当前范围上使用its closure。
export default class MyComponent extends Component {
state = {
counter: 42
}
myFunc = dynamicKey => e => {
// closure on the specific this.state.counter value at time of render.
}
}
虽然在每个渲染器上都返回一个新函数,但它的闭包在最近作用域
export default class MyComponent extends Component {
state = {
counter: 42
}
myFunc = dynamicKey => {
// closure on this.state.counter value
}
}
因此,这取决于用例。问问自己该函数是否需要特定值或最近的值。
注意:如果在每个渲染器上都重新声明了函数,它将成为一个“函数与咖喱函数之间的差异”的问题,对于React来说,这无关紧要,因为两个函数体都将被执行。因此,只有记住函数(不要使用相同的参数调用函数),您才能获得任何明显的区别。
您可以缓存事件处理程序。
class SomeComponent extends React.Component {
// Each instance of SomeComponent has a cache of click handlers
// that are unique to it.
clickHandlers = {};
// Generate and/or return a click handler,
// given a unique identifier.
getClickHandler = (key) => {
// If no click handler exists for this unique identifier, create one.
if (!this.clickHandlers[key])){
this.clickHandlers[key] = () => alert(key);
}
return this.clickHandlers[key];
}
render() {
return (
<ul>
{this.props.list.map(listItem =>
<li key={listItem.text}>
<Button onClick={this.getClickHandler(listItem.text)} />
</li>
)}
</ul>
);
}
}
请参阅以下article
如果使用React钩子,则:
const Button = props => {
const onClick = React.useMemo(() => {
alert(listItem.text)
}, [listItem.text]);
}
return <button onClick={onClick}>click</button>
}
如果您的函数不依赖于组件(没有此上下文),则可以在组件外部定义它。您的组件的所有实例都将使用相同的函数引用,因为该函数在所有情况下都是相同的。
与上一个示例相反,在每次渲染期间,createAlertBox均对内存中的相同位置保留相同的引用。因此,按钮不必重新渲染。
虽然Button可能是一个小的,快速呈现的组件,但您可能会在大型,复杂,缓慢呈现的组件上看到这些内联定义,并且它实际上会使您的React应用程序陷入困境。最好不要在render方法中定义这些函数。
如果您的函数确实依赖于组件,因此您无法在组件外部定义它,则可以将组件的方法作为事件处理程序传递:
在这种情况下,SomeComponent的每个实例都有一个不同的警报框。 Button的click事件侦听器对于SomeComponent必须是唯一的。通过传递createAlertBox方法,是否重新渲染SomeComponent无关紧要。消息道具是否更改甚至都没有关系! createAlertBox内存中的地址不会更改,这意味着Button不必重新渲染,从而节省了处理时间并提高了应用程序的渲染速度。
对于动态功能
在这种情况下,您有可变数量的按钮,使可变数量的事件监听器,每个都有独特的功能,您在创建SomeComponent时可能不知道什么。您如何解决这个难题?
输入备忘录,或简称为缓存的内容。对于每个唯一值,创建并缓存一个函数;对于将来对该唯一值的所有引用,请返回以前缓存的函数。