【问题标题】:How can I declare a variable inside brackets?如何在括号内声明变量?
【发布时间】:2019-06-10 09:11:18
【问题描述】:

我有一个像这样的渲染函数:

render() {
    const statement = true
    return (
      <div>
        {
          statement &&
          <div>
            <p>
              {this.buildStuff()}
            </p>
            <p>
              {this.buildStuff()}
            </p>
            <p>
              {this.buildStuff()}
            </p>
          </div>
        }
      </div>
    );
  }

为了避免调用buildStuff() 三次,我想将它分配给一个变量。如何在statement &amp;&amp; 行后声明变量?

一个快速的解决方案是做

const statement = true
const stuff = statement ? buildStuff() : null;

但是这个解决方案使用两个分支而不是一个。

您可以在StackBlitz 上试用此代码。

这就是它在Razor 中的样子。

【问题讨论】:

  • const stuff = statement ? buildStuff() : null; 有什么问题?
  • 为什么不能在return语句前做const ui = statement &amp;&amp; this.buildStuff(); return ... // just use ui here
  • @hindmost 为什么要在一个应该足够的情况下做出两个陈述?
  • @aloisdg 然后按照@Yury Tarabanko 的建议使用&amp;&amp;
  • @aloisdg 你会牺牲可读性而一无所获。真的没什么。顺便说一句,我敢打赌,Rajesh 的解决方案的性能不如检查布尔值:)。它创建一个数组、临时对象、将被 gced 的匿名函数,并添加另一个函数调用。

标签: javascript reactjs jsx


【解决方案1】:

第一个解决方案(编辑:替代)

render() {
    const statement = true;
    const stuff = this.buildStuff(statement, 3); // jsx result looped in divs
    return (
      <div>
        {
          statement &&
          <div>
            { stuff }
          </div>
        }
      </div>
    );
  }

如果这是您的目标,则另一种记忆化(函数缓存):

const memoize = require('fast-memoize');
const memoized = memoize(this.buildStuff);


...

render() {
    const statement = true; 
    return (
      <div>
        {
          statement &&
          <div>
            <p>
              {memoized()}
            </p>
            <p>
              {memoized()}
            </p>
            <p>
              {memoized()}
            </p>
          </div>
        }
      </div>
    );
  }

然而,memoization 的真正威力在于,如果您根据提供给 buildStuff 的参数进行缓存(也许您将语句移动到 buildstuff 中?)。在您的情况下,我只会清理组件和参数以提高可读性而不是优化某些内容。所以最后一个选择:

// Stuff is a component now
const Stuff = ({statement, stuff}) => {
  if(!statement)
    return null;

  const result = stuff();

  return (
    <div>   
      <p>
        {result}
      </p>
      <p>
        {result}
      </p>
      <p>
        {result}
      </p>
    </div>
  )
}

render() {
    return (
      <div>
        <Stuff statement={true} stuff={this.buildStuff} />
      </div>
    );
  }

好处是,你现在可以选择通过 props 传递结果或函数本身,在向下的组件中要么调用函数,要么直接传递其结果。

标题中对您的问题的单一回答:您不能,JSX 不像 Razor 那样是模板引擎。

解释:

// JSX  
<div id="foo">Hello world</div>

// Translates into 
React.createElement("div", {id: "foo"}, "Hello world");

// JSX
<div>{ statement && <div /> }</div>

// Translates to
React.createElement("div", null, statement && React.createElement("div"));

要么你声明一个带有属性的新变量,要么你不能,因为 javascript 不允许在函数的参数中创建变量。

【讨论】:

    【解决方案2】:

    此答案是问题的答案,但不是问题的解决方案。如果您不能在 react 中的括号内声明变量(例如在 Razor 中可以这样做)。一个语句调用两次仍然是你最好的选择。

    render() {
        const statement = true
        const stuff = statement ? this.buildStuff() : null
        return (
          <div>
            {
              statement &&
              <div>
                <p>
                  {stuff}
                </p>
                <p>
                  {stuff}
                </p>
                <p>
                  {stuff}
                </p>
              </div>
            }
          </div>
        );
      }
    

    至少,我们只在需要时调用this.buildStuff(),如果需要,我们只调用一次。

    【讨论】:

    • 签入:const stuff = statement ? this.buildStuff() : null 是多余的。 stuff 只会在真实情况下使用。这样做的唯一好处是,对于虚假价值,您根本没有调用函数。但是进行额外检查并没有多大意义
    【解决方案3】:

    你也可以试试这样的:

    • 您可以创建一个处理此 UI 表示的函数。
    • 在这个函数中,你可以调用buildStuff,让它返回3个&lt;p&gt;标签。
    • 然后在主渲染中,您可以检查您的条件并进行相应的渲染。这将使您的渲染干净且具有声明性。
    getBuildJSX() {
      const stuff = this.buildStuff();
      return Array.from({ length: 3}, () => <p> { stuff }</p>);
    }
    
    render() {
      const statement = true
      return (
        <div>
          {
            statement ? this.getBuilsJSX() : null
          }
        </div>
      );
    }
    

    Try it online

    【讨论】:

    • 好主意。由于我们不能在 JSX 中放置变量,我们使用一个函数来包装逻辑并将变量移动到其中。
    • @aloisdg 感谢您添加示例。它对我不开放,但应该帮助其他人
    【解决方案4】:

    我认为 React 的主要思想之一是使用组件来构建代码。

    所以一种方法是这样的:

    render() {
        const statement = true;
    
        const Stuff = ({statement}) => {
          if (!statement) { return null; }
          return this.buildStuff();
        }
    
        return (
          <div>
            <p>
              <Stuff statement={statement} /> 
            </p>
            <p>
              <Stuff statement={statement} />
            </p>
            <p>
              <Stuff statement={statement} />
            </p>
          </div>
        );
      }
    

    更新StackBlitz

    【讨论】:

    • AFAIK,在这里你将一个分支转换为三个,你仍然调用this.buildStuff() 三次。
    • 这增加了另一层间接性,仍然会调用buildStuff 三次
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-07-09
    • 1970-01-01
    • 2019-02-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多