我应该在每个渲染器上调用一个函数,还是在react类组件中使用箭头函数?

问题描述 投票:3回答:2

我有以下情况

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>
        )
    }
}

现在,我不在每个渲染上创建一个新函数,但在每个渲染上调用一个新函数。

现在我不确定要使用哪个。在每个函数上调用函数都是不好的做法吗?我应该使用箭头功能吗?

javascript reactjs arrow-functions
2个回答
0
投票

[使用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来说,这无关紧要,因为两个函数体都将被执行。因此,只有记住函数(不要使用相同的参数调用函数),您才能获得任何明显的区别。


-2
投票

您可以缓存事件处理程序。

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时可能不知道什么。您如何解决这个难题?

输入备忘录,或简称为缓存的内容。对于每个唯一值,创建并缓存一个函数;对于将来对该唯一值的所有引用,请返回以前缓存的函数。

© www.soinside.com 2019 - 2024. All rights reserved.