2
votes

Comment puis-je déclarer une variable entre crochets?

J'ai une fonction de rendu comme celle-ci:

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

Pour éviter d'appeler buildStuff () trois fois, je voudrais l'assigner à une variable. Comment puis-je déclarer une variable après la ligne avec statement && ?

Une solution rapide serait de faire

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

mais cette solution utilise deux branches au lieu d'une.

Vous pouvez essayer ce code sur StackBlitz .

Voici à quoi cela ressemblerait dans Razor .

p>


12 commentaires

Quel est le problème avec l'instruction const stuff =? buildStuff (): null; ?


Pourquoi ne pouvez-vous pas le faire avant l'instruction de retour const ui = statement && this.buildStuff (); return ... // utilisez simplement ui ici


@hindmost pourquoi faire deux déclarations alors qu'une seule devrait suffire?


@aloisdg Puis utilisez && comme @Yury Tarabanko l'a suggéré


@YuryTarabanko vous vérifiez toujours l'instruction booléenne deux fois.


Si vous vouliez vérifier la variable statement , vous pouvez remplacer son utilisation dans JSX par stuff : stuff && ...


@aloisdg Vous pouvez vérifier l'interface utilisateur à la place. :) La déclaration de variable est une instruction que vous ne pouvez pas utiliser dans une expression que vous souhaitez renvoyer. Vous pouvez déclarer let stuff; avant et utiliser l'opérateur virgule {statement && (stuff == this.buildStuff (), (

{stuff}
)} mais c'est moins lisible.


@hindmost je ne suis pas sûr de comprendre. Je suis nouveau pour réagir. Pourriez-vous des détails ou donner un exemple?


@YuryTarabanko n'est pas une mauvaise idée! Cela sent un peu plus une solution de contournement qu'une vraie solution mais l'idée est là. Je ne sacrifierai pas la lisibilité pour le gain de performance d'un bool (qui n'est presque rien)


@aloisdg Je ne le recommande PAS. const stuff = statement && this.buildStuff () est assez bon. La fonction buildStuff serait appelée 0 ou 1 fois. Vérifier que instruction booléenne est véridique ne coûte rien. Ne la micro-optimisez pas.


@YuryTarabanko Oui bien sûr, mais si je peux l'éviter sans aucun sacrifice, je le ferai. Dans le rasoir par exemple, c'est facile à réaliser


@aloisdg Vous sacrifieriez la lisibilité et ne gagneriez rien. Vraiment rien. BTW je parie que la solution de Rajesh est moins performante que la vérification d'un booléen :). Il crée un tableau, un objet temporaire, des fonctions anonymes qui seraient gced, et ajoute encore un autre appel de fonction.


4 Réponses :


0
votes

Je pense que l'une des principales idées de react est d'utiliser des composants pour structurer votre code.

Une façon de procéder serait donc la suivante:

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

Mise à jour StackBlitz .


2 commentaires

AFAIK, ici vous transformez un branchement en trois et vous appelez toujours this.buildStuff () trois fois.


Cela ajoute un autre niveau d'indirection et appellerait toujours buildStuff trois fois



3
votes

Vous pouvez également essayer quelque chose comme ceci:

  • Vous pouvez créer une fonction qui traite cette représentation de l'interface utilisateur.
  • Dans cette fonction, vous pouvez appeler buildStuff et lui faire renvoyer 3 balises

    .
  • Ensuite, dans le rendu principal, vous pouvez vérifier votre condition et effectuer le rendu en conséquence. Cela rendra votre rendu propre et déclaratif.
getBuildJSX() {
  const stuff = this.buildStuff();
  return Array.from({ length: 3}, () => <p> { stuff }</p>);
}

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

Essayez-le en ligne


2 commentaires

Bonne idée. Comme nous ne pouvons pas mettre de variable dans le JSX, nous utilisons une fonction pour envelopper la logique et y déplacer la variable.


@aloisdg Merci d'avoir ajouté un échantillon. Ce n'est pas une ouverture pour moi, mais devrait aider les autres



1
votes

Première solution (modifier: alternative)

// 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"));

Alternative, mémorisation (mise en cache des fonctions) si tel est votre objectif:

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

Le vrai pouvoir de la mémorisation est cependant, si vous mettez en cache en fonction du paramètre que vous donnez à buildStuff (peut-être que vous déplacez l'instruction dans buildstuff?). Dans votre cas, je nettoierais simplement le composant et les paramètres en faveur de la lisibilité plutôt que d'optimiser quelque chose. Donc dernière alternative:

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

L'avantage, vous pouvez maintenant choisir de passer le résultat ou la fonction elle-même à travers les accessoires, et dans le composant descendant soit appeler la fonction ou simplement avoir son résultats transmis.

Réponse unique à votre question dans le titre: vous ne pouvez pas, JSX n'est pas un moteur de création de modèles comme Razor.

Explication: p>

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

Soit vous déclarez une nouvelle variable avec un attribut, soit vous ne pouvez tout simplement pas, car javascript ne permet pas la création de variables à l'intérieur des paramètres des fonctions.


0 commentaires

0
votes

Cette réponse est une réponse au problème mais pas une solution à la question. Si vous ne pouvez pas déclarer une variable entre crochets dans react (comme vous pourriez le faire dans Razor par exemple). Appeler deux fois une instruction peut toujours être votre meilleur pari.

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

Au moins, nous appelons this.buildStuff () uniquement si nécessaire et si nous le faisons, nous l'appelons une seule fois.


1 commentaires

Vérifiez ceci: const stuff = statement? this.buildStuff (): null est redondant. stuff ne sera utilisé qu'en cas de vérité. Le seul avantage de ceci serait que, pour une valeur fausse, vous n'appelez pas du tout la fonction. Mais avoir un chèque supplémentaire n'a pas beaucoup de sens