web-dev-qa-db-fra.com

Erreur d'analyse: les éléments JSX adjacents doivent être enveloppés dans une balise englobante

J'essaie de configurer mon application React.js afin qu'elle ne s'affiche que si une variable que j'ai définie est vraie.

La façon dont ma fonction de rendu est configurée ressemble à ceci:

render: function() {
    var text = this.state.submitted ? 'Thank you!  Expect a follow up at '+email+' soon!' : 'Enter your email to request early access:';
    var style = this.state.submitted ? {"backgroundColor": "rgba(26, 188, 156, 0.4)"} : {};
    return (
    <div>

if(this.state.submitted==false) 
{

      <input type="email" className="input_field" onChange={this._updateInputValue} ref="email" value={this.state.email} />

      <ReactCSSTransitionGroup transitionName="example" transitionAppear={true}>
      <div className="button-row">
         <a href="#" className="button" onClick={this.saveAndContinue}>Request Invite</a>
     </div>
     </ReactCSSTransitionGroup>
}
   </div>
    )
  },

En gros, la partie importante ici est la partie if (this.state.submitted == false) (je veux que ces div apparaissent lorsque la variable soumise est définie sur false).

Mais lorsque je lance ceci, je reçois l'erreur dans la question:

Erreur non capturée: Erreur d'analyse: Ligne 38: Les éléments JSX adjacents doivent être encapsulés dans une balise englobante.

Quel est le problème ici? Et que puis-je utiliser pour faire ce travail?

392
user1072337

Vous devez placer votre composant entre une balise englobante, ce qui signifie:

// WRONG!

return (  
    <Comp1 />
    <Comp2 />
)

Au lieu:

// Correct

return (
    <div>
       <Comp1 />
       <Comp2 />
    </div>
)

Edit: Commentaire de Joe Clay à propos de API Fragments

// More Correct

return (
    <React.Fragment>
       <Comp1 />
       <Comp2 />
    </React.Fragment>
)
561
wdanxna

Réagir élément ne doit renvoyer qu'un seul élément. Vous devrez envelopper vos deux balises avec une autre balise d'élément.

Je peux aussi voir que votre fonction de rendu ne renvoie rien. Voici comment votre composant devrait ressembler à ceci:

var app = React.createClass({
    render () {
        /*React element can only return one element*/
        return (
             <div></div>
        )
    }
})

Notez également que vous ne pouvez pas utiliser d'instructions if à l'intérieur d'un élément retourné:

render: function() {
var text = this.state.submitted ? 'Thank you!  Expect a follow up at '+email+' soon!' : 'Enter your email to request early access:';
var style = this.state.submitted ? {"backgroundColor": "rgba(26, 188, 156, 0.4)"} : {};
    if(this.state.submitted==false) {
        return <YourJSX />
    } else {
        return <YourOtherJSX />
    }
},
107
Matan Gubkin

Si vous ne voulez pas le placer dans une autre division, comme d'autres réponses l'ont suggéré, vous pouvez également le placer dans un tableau et cela fonctionnera.

// Wrong!
return (  
   <Comp1 />
   <Comp2 />
)

Cela peut être écrit comme:

// Correct!
return (  
    [<Comp1 />,
    <Comp2 />]
)

Veuillez noter que ce qui précède générera un avertissement: Warning: Each child in an array or iterator should have a unique "key" prop. Check the render method of 'YourComponent'.

Cela peut être corrigé en ajoutant un attribut key aux composants, si vous les ajoutez manuellement, ajoutez-le comme ceci:

return (  
    [<Comp1 key="0" />,
    <Comp2 key="1" />]
)

Voici quelques informations supplémentaires sur les clés: Composition vs Héritage

88
Neal

Le problème

Erreur d'analyse: les éléments JSX adjacents doivent être enveloppés dans une balise englobante

Cela signifie que vous essayez de renvoyer plusieurs éléments JSX frères de manière incorrecte. N'oubliez pas que vous n'écrivez pas du HTML, mais du JSX! Votre code est transpilé de JSX en JavaScript. Par exemple:

render() {
  return (<p>foo bar</p>);
}

sera transpilé en:

render() {
  return React.createElement("p", null, "foo bar");
}

À moins que vous ne débutiez dans la programmation en général, vous savez déjà que les fonctions/méthodes (de n’importe quel langage) prennent un nombre quelconque de paramètres mais ne renvoient toujours que une valeur . Cela étant dit, vous pouvez probablement constater qu’un problème survient lorsque vous essayez de renvoyer plusieurs composants frères en fonction de la façon dont createElement() fonctionne; il ne prend que les paramètres de l'élément n et le renvoie. Par conséquent, nous ne pouvons pas renvoyer plusieurs éléments à partir d'un seul appel de fonction.


Donc, si vous vous êtes déjà demandé pourquoi cela fonctionne ...

render() {
  return (
    <div>
      <p>foo</p>
      <p>bar</p>
      <p>baz</p>
    </div>
  );
}

mais pas ça ...

render() {
  return (
    <p>foo</p>
    <p>bar</p>
    <p>baz</p>
  );
}

c'est parce que dans le premier extrait, les deux éléments <p>- font partie de children de l'élément <div>-. Lorsqu'ils font partie de children, nous pouvons alors exprimer un nombre illimité d'éléments frères. Jetez un coup d'œil à comment cela transpilerait:

render() {
  return React.createElement(
    "div",
    null,
    React.createElement("p", null, "foo"),
    React.createElement("p", null, "bar"),
    React.createElement("p", null, "baz"),
  );
}

Solutions

En fonction de la version de React que vous exécutez, vous disposez de quelques options pour remédier à cela:

  • Utiliser des fragments (React v16.2 + seulement!)

    À partir de React v16.2, React prend en charge les fragments , qui sont des composants sans nœud qui renvoie ses enfants directement.

    Le renvoi des enfants dans un tableau (voir ci-dessous) présente certains inconvénients:

    • Les enfants d'un tableau doivent être séparés par des virgules.
    • Les enfants dans un tableau doivent avoir une clé pour empêcher l’avertissement de clé de React.
    • Les chaînes doivent être entourées de guillemets.

    Ceux-ci sont éliminés de l'utilisation de fragments. Voici un exemple d'enfants enveloppés dans un fragment:

    render() {
      return (
        <>
          <ChildA />
          <ChildB />
          <ChildC />
        </>
      );
    }
    

    qui désucre en:

    render() {
      return (
        <React.Fragment>
          <ChildA />
          <ChildB />
          <ChildC />
        </React.Fragment>
      );
    }
    

    Notez que le premier extrait nécessite Babel v7.0 ou une version ultérieure.


  • Retourne un tableau (React v16.0 + seulement!)

    A partir de React v16, React, les composants peuvent renvoyer des tableaux. Cela diffère des versions antérieures de React dans lesquelles vous avez été obligé d'envelopper tous les composants frères dans un composant parent.

    En d'autres termes, vous pouvez maintenant faire:

    render() {
      return [<p key={0}>foo</p>, <p key={1}>bar</p>];
    }
    

    cela transpile en:

    return [React.createElement("p", {key: 0}, "foo"), React.createElement("p", {key: 1}, "bar")];
    

    Notez que ce qui précède renvoie un tableau. Les tableaux sont valides React Elements depuis React version 16 et ultérieure. Pour les versions précédentes de React, les tableaux ne sont pas des objets de retour valides!

    Notez également que ce qui suit est invalide (vous devez retourner un tableau):

    render() {
      return (<p>foo</p> <p>bar</p>);
    }
    

  • Envelopper les éléments dans un élément parent

    L’autre solution consiste à créer un composant parent qui englobe les composants frères dans son children. C’est de loin le moyen le plus courant de résoudre ce problème et fonctionne dans toutes les versions de React.

    render() {
      return (
        <div>
          <h1>foo</h1>
          <h2>bar</h2>
        </div>
      );
    }
    

    Remarque: Reportez-vous au début de cette réponse pour plus de détails et pour savoir comment cela est transposé .

48
Chris

Réagissez 16.0.0 nous pouvons renvoyer plusieurs composants à partir du rendu sous forme de tableau.

return ([
    <Comp1 />,
    <Comp2 />
]);

Réagissez 16.4.0 nous pouvons renvoyer plusieurs composants à partir du rendu dans une balise Fragment. fragment

return (
<React.Fragment>
    <Comp1 />
    <Comp2 />
</React.Fragment>);

Réaction future vous pourrez utiliser cette syntaxe abrégée. (de nombreux outils ne le supportant pas encore, vous voudrez peut-être écrire explicitement <Fragment> jusqu'à ce que l'outillage soit rattrapé.)

return (
<>
    <Comp1 />
    <Comp2 />
</>)
21
Morris S

Si vous n'emballez pas votre composant, vous pouvez l'écrire comme indiqué ci-dessous.

Au lieu de:

return(
  <Comp1 />
  <Comp2 />
     );

vous pouvez écrire ceci:

return[(
 <Comp1 />
),
(
<Comp2 />
) ];
7
ronak ganatra

c’est très simple, nous pouvons utiliser un élément parent parent pour envelopper tout l’élément ou utiliser le concept de composant d’ordre supérieur (HOC), très utile pour les applications qui réagissent js

render() {
  return (
    <div>
      <div>foo</div>
      <div>bar</div>
    </div>
  );
}

hOC est très simple, pas très compliqué. Ajoutez simplement un fichier hoc.js dans votre projet et ajoutez simplement ces codes.

const aux = (props) => props.children;
export default aux;

maintenant importer le fichier hoc.js où vous voulez utiliser, maintenant au lieu d'encapsuler avec un élément div, nous pouvons encapsuler avec hoc.

import React, { Component } from 'react';
import Hoc from '../../../hoc';

    render() {
      return (
    <Hoc>
        <div>foo</div>
        <div>bar</div>
    </Hoc>
      );
    }
4
Fazal

Il existe une règle dans Réaction selon laquelle une expression JSX doit comporter exactement un élément le plus externe.

faux

const para = (
    <p></p>
    <p></p>
);

correct

const para = (
    <div>
        <p></p>
        <p></p>
    </div>
);
2
Khandelwal-manik

Les composants React doivent être emballés dans un seul conteneur, qui peut être n’importe quelle balise par exemple, "<div> .. </ div>"

Vous pouvez vérifier la méthode de rendu de ReactCSSTransitionGroup

2
Shivprasad P

React 16 obtient votre retour sous forme de tableau, il doit donc être entouré d'un seul élément, tel que div.

Mauvaise approche

render(){
    return(
    <input type="text" value="" onChange={this.handleChange} />

     <button className="btn btn-primary" onClick=   {()=>this.addTodo(this.state.value)}>Submit</button>

    );
}

bonne approche (tous les éléments d’une div ou autre élément que vous utilisez)

render(){
    return(
        <div>
            <input type="text" value="" onChange={this.handleChange} />

            <button className="btn btn-primary" onClick={()=>this.addTodo(this.state.value)}>Submit</button>
        </div>
    );
}
2
Abdul Moiz

Invalid:Pas seulement des éléments enfants

render(){
        return(
            <h2>Responsive Form</h2>
            <div>Adjacent JSX elements must be wrapped in an enclosing tag</div>
            <div className="col-sm-4 offset-sm-4">
                <form id="contact-form" onSubmit={this.handleSubmit.bind(this)} method="POST">
                    <div className="form-group">
                        <label for="name">Name</label>
                        <input type="text" className="form-control" id="name" />
                    </div>
                    <div className="form-group">
                        <label for="exampleInputEmail1">Email address</label>
                        <input type="email" className="form-control" id="email" aria-describedby="emailHelp" />
                    </div>
                    <div className="form-group">
                        <label for="message">Message</label>
                        <textarea className="form-control" rows="5" id="message"></textarea>
                    </div>
                    <button type="submit" className="btn btn-primary">Submit</button>
                </form>
            </div>
        )
    }

Valid:élément racine sous les éléments enfants

render(){
        return(
          <div>
            <h2>Responsive Form</h2>
            <div>Adjacent JSX elements must be wrapped in an enclosing tag</div>
            <div className="col-sm-4 offset-sm-4">
                <form id="contact-form" onSubmit={this.handleSubmit.bind(this)} method="POST">
                    <div className="form-group">
                        <label for="name">Name</label>
                        <input type="text" className="form-control" id="name" />
                    </div>
                    <div className="form-group">
                        <label for="exampleInputEmail1">Email address</label>
                        <input type="email" className="form-control" id="email" aria-describedby="emailHelp" />
                    </div>
                    <div className="form-group">
                        <label for="message">Message</label>
                        <textarea className="form-control" rows="5" id="message"></textarea>
                    </div>
                    <button type="submit" className="btn btn-primary">Submit</button>
                </form>
            </div>
          </div>
        )
    }
1
KARTHIKEYAN.A

Importer la vue et la placer dans View. Envelopper dans un div n'a pas fonctionné pour moi.

import { View } from 'react-native';
...
    render() {
      return (
        <View>
          <h1>foo</h1>
          <h2>bar</h2>
        </View>
      );
    }
1
Ocko

Pour les développeurs Rect-Native. Je rencontre cette erreur lors du renduItem dans FlatList. J'ai eu deux composants de texte. Je les utilisais comme ci-dessous

renderItem = { ({item}) => 
     <Text style = {styles.item}>{item.key}</Text>
     <Text style = {styles.item}>{item.user}</Text>
}

Mais après avoir mis ces câbles dans Inside View Components, cela a fonctionné pour moi.

renderItem = { ({item}) => 
   <View style={styles.flatview}>
      <Text style = {styles.item}>{item.key}</Text>
      <Text style = {styles.item}>{item.user}</Text>
   </View>
 }

Vous utilisez peut-être d'autres composants, mais vous pouvez les intégrer dans View.

0
GSK