recorrer react component array javascript reactjs render

javascript - react - Error de análisis: los elementos JSX adyacentes deben estar envueltos en una etiqueta adjunta



render component react (14)

Estoy tratando de configurar mi aplicación React.js para que solo se muestre si una variable que configuré es verdadera.

La forma en que está configurada mi función de renderización es la siguiente:

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

Básicamente, la parte importante aquí es la parte if (this.state.submitted == false) (quiero que estos divs se muestren cuando la variable enviada se establezca en false).

Pero cuando ejecuto esto, aparece el error en la pregunta:

Error no detectado: Error de análisis: Línea 38: Los elementos JSX adyacentes deben estar envueltos en una etiqueta adjunta

Cuál es el problema aquí? ¿Y qué puedo usar para que esto funcione?


El problema

Error de análisis: los elementos JSX adyacentes deben estar envueltos en una etiqueta adjunta

Esto significa que está intentando devolver varios elementos JSX hermanos de manera incorrecta. ¡Recuerde que no está escribiendo HTML, sino JSX! Su código se transpila de JSX a JavaScript. Por ejemplo:

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

será trasladado a:

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

A menos que sea nuevo en la programación en general, ya sabe que las funciones / métodos (de cualquier lenguaje) toman cualquier número de parámetros pero siempre solo devuelven un valor. Dado eso, probablemente pueda ver que surge un problema al intentar devolver múltiples componentes hermanos en función de cómo funciona createElement() ; solo toma parámetros para un elemento y lo devuelve. Por lo tanto, no podemos devolver múltiples elementos de una llamada de función.

Entonces, si alguna vez te has preguntado por qué esto funciona ...

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

pero no esto ...

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

es porque en el primer fragmento, ambos elementos <p> son parte de los elementos secundarios del elemento <div> . Cuando son parte de children entonces podemos expresar un número ilimitado de elementos hermanos. Eche un vistazo a cómo se transpilaría esto:

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

Soluciones

Dependiendo de la versión de React que esté ejecutando, tiene algunas opciones para abordar esto:

  • Usar fragmentos (¡React v16.2 + solo!)

    A partir de React v16.2, React tiene soporte para Fragments, que es un componente sin nodo que devuelve sus hijos directamente.

    Devolver a los hijos en una matriz (ver más abajo) tiene algunos inconvenientes:

    • Los niños en una matriz deben estar separados por comas.
    • Los niños en una matriz deben tener una clave para evitar la advertencia de clave de React.
    • Las cadenas deben estar entre comillas.

    Estos se eliminan del uso de fragmentos. Aquí hay un ejemplo de niños envueltos en un fragmento:

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

    que quita el azúcar en:

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

    Tenga en cuenta que el primer fragmento requiere Babel v7.0 o superior.

  • Devuelve una matriz (¡solo React v16.0 +!)

    A partir de React v16, React Components puede devolver matrices. Esto es diferente a las versiones anteriores de React donde se vio obligado a envolver todos los componentes hermanos en un componente principal.

    En otras palabras, ahora puedes hacer:

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

    esto se traduce en:

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

    Tenga en cuenta que lo anterior devuelve una matriz. Las matrices son elementos de reacción válidos desde React versión 16 y posteriores. ¡Para versiones anteriores de React, las matrices no son objetos de retorno válidos!

    También tenga en cuenta que lo siguiente no es válido (debe devolver una matriz):

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

  • Envuelva los elementos en un elemento padre

    La otra solución consiste en crear un componente principal que envuelva los componentes hermanos en sus elementos children . Esta es, con mucho, la forma más común de abordar este problema y funciona en todas las versiones de React.

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

    Nota: Eche un vistazo nuevamente a la parte superior de esta respuesta para obtener más detalles y cómo se transmite .


Debe colocar su componente entre una etiqueta adjunta, lo que significa:

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

En lugar:

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

Editar: según el comentario de Joe Clay sobre la API Fragments

// More Correct return ( <React.Fragment> <Comp1 /> <Comp2 /> </React.Fragment> )


Es tarde para responder esta pregunta, pero pensé que se agregaría a la explicación.

Está sucediendo porque en cualquier parte de su código está devolviendo dos elementos simultáneamente.

p.ej

return( <div id="div1"></div> <div id="div1"></div> )

Debe estar envuelto en un elemento padre . p.ej

return( <div id="parent"> <div id="div1"></div> <div id="div1"></div> </div> )

Explicación más detallada

Su código jsx continuación se transforma

class App extends React.Component { render(){ return ( <div> <h1>Welcome to React</h1> </div> ); } }

dentro de esto

_createClass(App, [{ key: ''render'', value: function render() { return React.createElement( ''div'', null, React.createElement( ''h1'', null, ''Welcome to React'' ) ); } }]);

Pero si haces esto

class App extends React.Component { render(){ return ( <h1>Welcome to React</h1> <div>Hi</div> ); } }

esto se convierte en esto (solo con fines ilustrativos, en realidad obtendrá un error : Adjacent JSX elements must be wrapped in an enclosing tag )

_createClass(App, [{ key: ''render'', value: function render() { return React.createElement( ''div'', null, ''Hi'' ); return React.createElement( ''h1'', null, ''Welcome to React'' ) } }]);

En el código anterior, puede ver que está intentando regresar dos veces desde una llamada de método, lo que obviamente es incorrecto.

Editar: últimos cambios en React 16 y en los propios barrios:

Si no desea agregar div extra para ajustar y desea devolver más que en los componentes secundarios, puede React.Fragments .

React.Fragments son un poco más rápidos y tienen menos uso de memoria (no es necesario crear un nodo DOM adicional, menos árbol DOM desordenado).

por ejemplo (en React 16.2.0)

render() { return ( <> React fragments. <h2>A heading</h2> More React fragments. <h2>Another heading</h2> Even more React fragments. </> ); }

o

render() { return ( <React.Fragments> React fragments. <h2>A heading</h2> More React fragments. <h2>Another heading</h2> Even more React fragments. <React.Fragments/> ); }

o

render() { return [ "Some text.", <h2 key="heading-1">A heading</h2>, "More text.", <h2 key="heading-2">Another heading</h2>, "Even more text." ]; }


Hay una regla en reaccionar que una expresión JSX debe tener exactamente un elemento más externo.

incorrecto

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

correcto

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


Importar vista y envolver en View . Envolver en un div no funcionó para mí.

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


Los componentes de reacción deben envolverse en un solo contenedor, que puede ser cualquier etiqueta, por ejemplo, "<div> .. </ div>"

Puede verificar el método de representación de ReactCSSTransitionGroup


Para desarrolladores Rect-Native. Me encuentro con este error al renderizar el elemento en FlatList. Tenía dos componentes de texto. Los estaba usando como a continuación

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

Pero después de poner estos componentes Tow View View internos, funcionó para mí.

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

Es posible que esté utilizando otros componentes, pero ponerlos en Vista puede funcionar para usted.


Reaccionar elemento tiene que devolver solo un elemento. Tendrás que envolver ambas etiquetas con otra etiqueta de elemento.

También puedo ver que su función de renderizado no devuelve nada. Así es como debería verse su componente:

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

También tenga en cuenta que no puede usar las declaraciones if dentro de un elemento devuelto:

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 /> } },


React 16 obtiene su retorno como una matriz, por lo que debe estar envuelto por un elemento como div.

Enfoque equivocado

render(){ return( <input type="text" value="" onChange={this.handleChange} /> <button className="btn btn-primary" onClick= {()=>this.addTodo(this.state.value)}>Submit</button> ); }

Enfoque correcto (Todos los elementos en un div u otro elemento que está utilizando)

render(){ return( <div> <input type="text" value="" onChange={this.handleChange} /> <button className="btn btn-primary" onClick={()=>this.addTodo(this.state.value)}>Submit</button> </div> ); }


Si no ajusta su componente, puede escribirlo como se menciona a continuación.

En vez de:

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

puedes escribir esto:

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


Si no desea envolverlo en otro div como lo han sugerido otras respuestas, también puede envolverlo en una matriz y funcionará.

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

Se puede escribir como:

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

Tenga en cuenta que lo anterior generará una advertencia: Warning: Each child in an array or iterator should have a unique "key" prop. Check the render method of ''YourComponent''. Warning: Each child in an array or iterator should have a unique "key" prop. Check the render method of ''YourComponent''.

Esto se puede solucionar agregando un atributo key a los componentes, si agrega estos manualmente, agréguelo como:

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

Aquí hay más información sobre las claves: Composición vs Herencia


es muy simple, podemos usar un elemento padre div para envolver todo el elemento o podemos usar el concepto de Componente de orden superior (HOC), es decir, muy útil para aplicaciones de reacción js

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

u otra mejor manera es HOC, es muy simple, no muy complicado, solo agregue un archivo hoc.js en su proyecto y simplemente agregue estos códigos

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

ahora importa el archivo hoc.js donde quieras usar, ahora en lugar de envolver con el elemento div podemos envolver con hoc.

import React, { Component } from ''react''; import Hoc from ''../../../hoc''; render() { return ( <Hoc> <div>foo</div> <div>bar</div> </Hoc> ); }


Inválido: no solo elementos secundarios

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

Válido: elemento raíz debajo de elementos secundarios

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


React 16.0.0 podemos devolver múltiples componentes de render como una matriz.

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

React 16.4.0 podemos devolver múltiples componentes desde render en una etiqueta Fragment. Fragmento

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

Future React podrá utilizar esta sintaxis abreviada. (muchas herramientas aún no lo admiten, por lo que es posible que desee escribir explícitamente <Fragment> hasta que las herramientas se pongan al día).

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