【问题标题】:Declaring function inside function in React在 React 中的函数内部声明函数
【发布时间】:2019-08-28 15:00:25
【问题描述】:

我刚刚遇到了一个 React 代码,我不确定这是否是一个好方法。这是该代码的示例实现。

class App extends React.Component {
  renderMessage = () => {
    function getMessage() {
      return "Hello"
    } 
    function getName() {
      return "Vijay"
    }
    return (
      <h1>{getMessage()} {getName()} !!!</h1>
    )
  }
  render() {
    return (
      <div>
        {this.renderMessage()}
      </div>
    )
  }
}

这里我们在渲染中调用了一个函数renderMessage。在renderMessage 中有两个内部函数,它们仅在renderMessage 内部调用。我现在的问题是:-

  • 这是一个好方法吗?它不会在每次render 调用时重新声明方法getNamegetMessage
  • 如果我创建getNamegetMessage 类方法并在renderMessage 中调用它们,会不会是一种改进?

谢谢:)

【问题讨论】:

  • 看起来很奇怪 - 我更喜欢使用标准的类方法,除非有理由不这样做
  • 除非类足够大以至于您想将getMessagegetName only 封装在renderMessage 中,这就是您想要做的吗?这个目标是有意义的
  • 这里的目标是这些方法只在renderMessage内部使用是否公平,因为除了renderMessage之外没有人会使用它们。

标签: javascript reactjs redux


【解决方案1】:

这是一个好方法吗?它不会在每次渲染调用时重新声明方法 getName 和 getMessage

绝对不是一个好方法。因为 JavaScript 要么具有功能范围,要么具有块或全局范围。 您在此范围内定义的任何内容都将仅属于此范围。在您的情况下,这些函数 getMessagegetName 将是 renderMessage 的一部分,这是函数范围。

在每次调用时,都会定义新函数,而不是重用之前定义的函数。

如果我创建 getName 和 getMessage 类方法并在 renderMessage 中调用它们会是一种改进吗?

依赖。 如果此函数需要访问任何组件属性或方法,则应将其放置在组件中,或者如果这只是实用程序函数,则将其放置在与组件分开的辅助库中。 当然,这会有所作为。

【讨论】:

    【解决方案2】:

    这是一个好方法吗?它不会在每次渲染调用时重新声明方法 getName 和 getMessage。

    它将在每次渲染调用时重新清除 函数 getNamegetMessage。这不是很好,但并不可怕。这种方法减少了重新渲染的错误——函数声明是渲染结果的一部分。尽管在您的确切情况下这无关紧要,因为函数将始终返回相同的结果并且它不依赖于状态(尽管在这种情况下,仅内联字符串会更具可读性)

    如果我创建 getNamegetMessage 类方法并在 renderMessage 中调用它们会是一种改进吗?

    这将使垃圾收集器的 virtual 生活更轻松。很有可能,一旦你开始依赖全局状态,这将开始出错,例如:

    class App extends React.Component {
      getMessage => () {
          return "Hello"
        } 
      getName => () {
        return this.props.name
      }
    
      renderMessage = () => {
        someHttpAction().then(() => {
            alert(getMessage() + ' ' + getName());
        })
      }
      render() {
        return (
          <div onclick={this.renderMessage}>Say my name! (Hint, its {this.props.name})</div>
        )
      }
    }
    

    (请注意,名称是作为App 的参数传入的)

    当您第一次渲染时,您可能会期望在单击文本后,您会看到“Hello Vijay”的警报。这是真的,大多数时候。但是,如果在单击文本后,使用不同的 name 值重新渲染,例如 Heisenberg,而 someHttpAction 承诺仍未解决,会发生什么情况?您可能希望看到您的名字 - Vijay,但实际上您会看到新值“Hello Heisenberg”。通过声明函数内联(根据您的示例),函数的范围被锁定,您将获得预期的结果“Hello Vijay”。

    想象一个更复杂的场景,您在多个用户配置文件之间切换并且异步消息开始显示在错误的用户身上...

    虽然是的,但我们可以将 name 作为参数传递给 getName,但实际上,人们认为“这次没问题”或者忘记了,这就是引入错误的方式。使用内联函数犯同样的错误要容易得多。除非这成为瓶颈,否则请坚持使用不易出错的方法。

    另外,我建议浏览一下How Are Function Components Different from Classes?

    【讨论】:

      【解决方案3】:

      这是可能的,但这根本不是一个好的解决方案。

      是的,它会在每次重新渲染时创建新函数,但如果您不将它们作为道具传递,则情况并非如此。

      问题是你可以在不久的将来得到一个职责非常模糊的巨型怪物组件。

      更多。在性能方面很糟糕。您的组件越大,重新渲染所需的时间就越长。而且每一个最小的变化都会重新渲染整个组件,而不仅仅是它的一部分。

      为了可读性和可扩展性,您应该将 renderMessage 方法移至新组件。

      class App extends React.Component {
        render() {
          return (
            <div>
              <Message/>
            </div>
          )
        }
      }
      
      class Message extends React.Component {
          getMessage() {
            return "Hello"
          } 
          
          getName() {
            return "Vijay"
          }
          
          render() {
            return (
              <h1>{this.getMessage()} {this.getName()} !!!</h1>
            )
          }
      }

      【讨论】:

        猜你喜欢
        • 2017-12-20
        • 2015-06-27
        • 1970-01-01
        • 2020-10-22
        • 2011-06-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多