구문 분석 오류 : 인접한 JSX 요소를 묶는 태그로 묶어야합니다.


467

내가 설정 React.js한 변수가 인 경우에만 렌더링되도록 앱 을 설정하려고합니다 true.

렌더링 기능 설정 방법은 다음과 같습니다.

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

기본적으로 여기서 중요한 부분은 if(this.state.submitted==false)부분입니다 ( div제출 된 변수가로 설정되면 이러한 요소가 표시 되기를 원합니다 false).

그러나 이것을 실행할 때 질문에 오류가 발생합니다.

잡히지 않는 오류 : 구문 분석 오류 : 38 행 : 인접한 JSX 요소를 묶는 태그로 묶어야합니다.

여기서 문제는 무엇입니까? 이 작업을 위해 무엇을 사용할 수 있습니까?


3
stackoverflow.com/questions/25034994/… 여기있는 다른 사람들은 단지 부모 요소를 사용하라고 말하고 있지만 불필요 할 수도 있습니다. 이 이전 버전의 질문에는 배열을 사용하는 흥미로운 답변이 있습니다.
Meow

답변:


636

구성 요소를 묶는 태그 사이에 두어야합니다. 즉,

// WRONG!

return (  
    <Comp1 />
    <Comp2 />
)

대신 :

// Correct

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

편집 : Fragments API에 대한 Per Joe Clay의 의견

// More Correct

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

// Short syntax

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

4
테이블에 2 행을 함께 인쇄하면 어떻게됩니까? <tr>을 어떻게 감쌀 수 있습니까?
Jose

235

이 질문에 대답하기는 늦었지만 설명에 추가 할 것이라고 생각했습니다.

코드의 어느 위치에서나 두 요소를 동시에 반환하기 때문에 발생합니다.

예 :

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

부모 요소 로 싸야 합니다. 예 :

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


더 자세한 설명

아래 jsx코드가 변형됩니다

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

이것으로

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

하지만 이렇게하면

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

이것은 이것으로 변환됩니다 (일러스트 목적으로 실제로, 당신은 얻을 것입니다 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'
        )
    }
  }]);

위의 코드 에서 메소드 호출에서 두 번 리턴하려고 시도하고 있음을 알 수 있습니다 .

React 16 및 최신 버전의 최신 변경 사항 :

랩을 위해 여분의 div를 추가하고 싶지 않고 둘 이상의 하위 구성 요소를 반환하려는 경우 사용할 수 있습니다 React.Fragments.

React.Fragments 약간 더 빠르며 메모리 사용량이 적습니다 (추가 DOM 노드를 만들 필요가 없으며 덜 복잡한 DOM 트리가 필요 없음).

(React 16.2.0에서)

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

또는

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

또는

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

115

리 액트 요소는 하나의 요소 만 반환해야합니다. 두 요소를 다른 요소 태그로 감싸 야합니다.

또한 렌더링 함수가 아무것도 반환하지 않는 것을 볼 수 있습니다. 구성 요소는 다음과 같습니다.

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

또한 if반환 된 요소 내 에서는 문을 사용할 수 없습니다 .

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

이 "if"문제를 해결하지 않습니다; render 함수 내에서 "if"를 제거하면 정상적으로 작동합니다.
user1072337

1
재조정 된 요소 내부의 명령문이있는 경우 사용할 수 없습니다. 내 업데이트 된 답변을 봐
Matan Gubkin

99

다른 답변에서 제안한 것처럼 다른 div에 래핑하지 않으려면 배열로 래핑하면 작동합니다.

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

다음과 같이 쓸 수 있습니다.

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

위의 내용은 경고를 생성합니다. Warning: Each child in an array or iterator should have a unique "key" prop. Check the render method of 'YourComponent'.

key수동으로 추가하면 다음과 같이 속성을 구성 요소 에 추가하여 문제를 해결할 수 있습니다 .

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

키에 대한 추가 정보는 다음과 같습니다. 컴포지션 vs 상속


7
나는 이것을 시도했고 그것은 나에게 오류를 준다. 유효한 React 요소 (또는 null)가 반환되어야합니다. undefined, array 또는 다른 잘못된 객체를 반환했을 수 있습니다.
prasadmsvs

3
@prasadmsvs +1 invariant.js : 39 Uncaught Invariant Violation : CommitFilter.render () : 유효한 ReactComponent를 반환해야합니다. undefined, array 또는 다른 잘못된 객체를 반환했을 수 있습니다.
스베틀라나 이바노 바

1
이것은 래퍼 요소를 피하기 위해 필요하거나 원할 때 훌륭한 솔루션입니다!
bloudermilk

2
@aaaaaa 현재 React 조정자가 작동하는 방식으로 인해 불가능합니다. 스택이며 조정이 재귀 적으로 수행됩니다. React 16에서는 이것이 수정되었으며 이제 배열을 반환 할 수 있습니다.
natnai

1
github.com/iamdustan/tiny-react-renderer 는 모든 반응 개발자가 읽어야 할 훌륭한 저장소입니다. 일단 당신이 그렇게한다면, 현재의 반응 구현이 여러 아이를 돌려주는 것을 허용하지 않는 이유는 당신에게 즉시 명백해 져야합니다.
natnai

49

문제

구문 분석 오류 : 인접한 JSX 요소를 묶는 태그로 묶어야합니다.

이는 여러 형제 JSX 요소를 잘못된 방식으로 반환하려고 함을 의미합니다. HTML을 작성하는 것이 아니라 JSX를 작성한다는 것을 기억하십시오! 코드가 JSX에서 JavaScript로 변환되었습니다. 예를 들면 다음과 같습니다.

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

다음으로 번역됩니다 :

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

일반적으로 프로그래밍에 익숙하지 않은 한, 함수 / 메소드 (모든 언어)는 여러 매개 변수를 사용하지만 항상 하나의 값만 반환한다는 것을 이미 알고 있습니다 . 이를 감안할 때 createElement()작동 방식에 따라 여러 형제 구성 요소를 반환하려고 할 때 문제가 발생했음을 알 수 있습니다 . 하나의 요소에 대해서만 매개 변수를 취하여이를 리턴합니다. 따라서 하나의 함수 호출에서 여러 요소를 반환 할 수 없습니다.


왜 이것이 효과가 있는지 궁금하다면 ...

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

그러나 이것은 ...

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

첫 번째 코드에서 두 때문이다 <p>-elements 중 일부 children<div>- 요소. 그것들이 일부일 때 children우리는 무제한의 형제 요소를 표현할 수 있습니다. 이것이 어떻게 변환되는지 살펴보십시오.

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

솔루션

실행중인 React 버전에 따라이를 해결하기위한 몇 가지 옵션이 있습니다.

  • 조각 사용 (React v16.2 + 만 해당)

    React v16.2부터 React는 자식을 직접 반환하는 노드가없는 구성 요소 인 Fragments 를 지원합니다 .

    배열에서 자식을 반환하면 (아래 참조) 몇 가지 단점이 있습니다.

    • 배열의 자식은 쉼표로 구분해야합니다.
    • 배열의 자식에는 React의 키 경고를 방지하기위한 키가 있어야합니다.
    • 문자열은 따옴표로 묶어야합니다.

    이들은 프래그먼트를 사용하여 제거됩니다. 다음은 조각으로 싸인 아이들의 예입니다.

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

    어떤 설탕을 제거 하는가?

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

    첫 번째 스 니펫에는 Babel v7.0 이상이 필요합니다.


  • 배열 반환 (React v16.0 + 만 해당)

    React v16부터 React Components는 배열을 반환 할 수 있습니다. 이것은 모든 형제 컴포넌트를 상위 컴포넌트에 랩핑해야하는 이전 버전의 React와 다릅니다.

    즉, 이제 다음을 수행 할 수 있습니다.

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

    이것은 다음으로 번역됩니다.

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

    위의 배열을 반환합니다. 배열은 React 버전 16 이상부터 유효한 React 요소입니다. 이전 버전의 React의 경우 배열은 유효한 반환 객체가 아닙니다!

    또한 다음은 유효하지 않습니다 (배열을 반환해야 함).

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

  • 부모 요소로 요소 감싸기

    다른 솔루션에는 형제 구성 요소를 포함하는 상위 구성 요소를 만드는 것이 포함됩니다 children. 이것은이 문제를 해결하는 가장 일반적인 방법이며 모든 버전의 React에서 작동합니다.

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

    참고 : 자세한 내용과이 변환 방법에 대해서는이 답변 상단을 다시 살펴보십시오 .


@Grievoushead, 구성 요소가 아닙니다. 어린이 만.
Chris

1
좋은 문제가 해결되었습니다.
Sohan

1
다른 솔루션을 설명 할 시간을 내 주셔서 감사합니다.
Marvel Moe

React v16.4에서 첫 번째 예제는 다음을 사용하여 작동하지 않습니다. <>, only <React.Fragment>:(
vsync

@vsync 해당 구문에 대한 지원은 건물 환경에 따라 다릅니다. babel이 아직 지원하는지, 그렇다면 어떤 버전인지 확실하지 않습니다.
Chris

22

React 16.0.0 렌더에서 여러 컴포넌트를 배열로 반환 할 수 있습니다.

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

React 16.4.0 에서는 Fragment 태그의 여러 컴포넌트를 렌더링에서 반환 할 수 있습니다. 파편

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

향후 React 에서는이 속기 구문을 사용할 수 있습니다. (많은 툴은 아직 지원하지 않으므로 <Fragment>툴링이 잡힐 때까지 명시 적으로 작성 하는 것이 좋습니다.)

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

1
,구성 요소 간을 잊었습니다 . 배열이므로 각 요소를 분리해야합니다.
Chris

더있다 <Fragment>, 그것은 없습니다 <React.Fragment>. 귀하의 링크에서 그렇게 말합니다
vsync

2
당신이 파괴하는 경우 import React { Fragment } from 'react';다음과 같이 사용합니다<Fragment >
Morris S

7

구성 요소를 포장하지 않으면 아래 언급 된 방법으로 작성할 수 있습니다.

대신에:

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

당신은 이것을 쓸 수 있습니다 :

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

6

부모 요소 div를 사용하여 모든 요소를 ​​래핑하거나 고차 구성 요소 (HOC 's) 개념을 사용할 수 있습니다. 즉, 반응 js 응용 프로그램에 매우 유용합니다.

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

또는 다른 가장 좋은 방법은 HOC가 매우 간단하지는 않지만 매우 복잡하지는 않습니다. 프로젝트에 파일 hoc.js를 추가하고 단순히 이러한 코드를 추가하십시오.

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

이제 사용하려는 hoc.js 파일을 가져 오십시오. 이제 div 요소로 감싸는 대신 hoc로 줄 바꿈 할 수 있습니다.

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

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

이 코드는 질문에 대답 할 수 있지만 문제를 해결하는 방법 및 / 또는 이유에 대한 추가 컨텍스트를 제공하면 답변의 장기적인 가치가 향상됩니다. 이것을 읽으십시오 .
Shanteshwar Inde

이것은 HoC가 아니며 구성 요소의 기능을 복제하는 간단한 구성 Fragment요소입니다.
Emile Bergeron

4

JSX 표현식에는 정확히 하나의 가장 바깥 쪽 요소가 있어야한다는 규칙이 있습니다.

잘못된

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

옳은

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

1

React 16은 반환 값을 배열로 가져 오므로 div와 같은 하나의 요소로 감싸 야합니다.

잘못된 접근

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

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

    );
}

올바른 접근 방식 (한 div의 모든 요소 또는 사용중인 다른 요소)

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

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

1

리 액트 컴포넌트는 단일 컨테이너에 래퍼되어야합니다 ( 예 : "<div> .. </ div>").

ReactCSSTransitionGroup의 렌더링 방법을 확인할 수 있습니다


0

뷰를 가져 와서 래핑 View합니다. 에 싸서 div나를 위해 작동하지 않았다.

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

2
반응 네이티브를 사용하고 있기 때문입니다.
Nick H247

React Native에서도 프래그먼트를 사용할 수 있으므로 View실제로 최상의 솔루션은 아닙니다.
Emile Bergeron

0

유효 하지 않음 : 하위 요소뿐만 아니라

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

유효 : 하위 요소 아래의 루트 요소

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

추가 할 내용이없는 한 "나도"유형 답변이나 동일한 솔루션을 반복하지 마십시오 .
Emile Bergeron

-1

Rect-Native 개발자에게 적합합니다. FlatList에서 item을 렌더링하는 동안이 오류가 발생합니다. 두 개의 텍스트 구성 요소가 있습니다. 나는 아래처럼 그들을 사용하고 있었다

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

그러나이 견인 인사이드 뷰 구성 요소를 넣은 후에는 효과가있었습니다.

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

다른 구성 요소를 사용하고 있지만 View에 배치하면 효과가있을 수 있습니다.


React Native에서도 조각을 사용할 수 있으므로 View실제로 최상의 솔루션은 아닙니다.
Emile Bergeron

-1

return 문 내에 여러 Div를 중첩하려고 할 때 합병증이 발생할 수 있다고 생각합니다. 컴포넌트가 블록 요소로 렌더링되도록하기 위해이 작업을 수행 할 수 있습니다.

다음은 여러 div를 사용하여 몇 가지 구성 요소를 올바르게 렌더링하는 예입니다.

return (
  <div>
    <h1>Data Information</H1>
    <div>
      <Button type="primary">Create Data</Button>
    </div>
  </div>
)

-1

이 오류가 발생하여 모두 명백하지 않은 문제가 발생했습니다.

const App = () => {
  return (
      <div className="App">
        <h1>Hello CodeSandbox</h1>
        <h2>Start editing to see some magic happen!</h2>
      </div>
  )
}

그리고 여기 수정이있었습니다 ...

const App = () => {
  return (
      <div className="AppClassName">       <--- note the change
        <h1>Hello CodeSandbox</h1>
        <h2>Start editing to see some magic happen!</h2>
      </div>
  )
}

그림을 이동. 다른 사람들이이 충돌에 부딪 칠 경우를 대비하여 정보를 공유했습니다. 분명히 React 부모 함수 이름과 동일한 요소 클래스 이름을 가질 수 없습니다.


그건 사실이 아니야. codesandbox React 템플릿의 기본값이기도합니다. 다른 것이이 클래스 이름과 충돌했을 것입니다.
Emile Bergeron
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.