[React.JS] JSX, props, state 학습하기

Dico·2020년 12월 17일
0

[React.JS]

목록 보기
2/3

1. JSX (JavaScript XML)

React JSX: JavaScript언어의 확장.
JavaScript에서 HTML형식을 그대로 사용할 수 있게 하는 등 XML과 같은 문법을 native JavaScript로 변환해줌.


2. React.createElement()와 JSX

Syntax:
React.createElement(component, props, ...children)

React.createElement()메소드는 최소 3개의 인자를 전달 받는다.
첫번째는 component(tag),
두번째는 configuration(props),
세번째는 children.

//ex
return React.createElement('div', {className: 'App'}, React.createElement('h1', null, 'Hi, I\'m a React App'))

React.createElement()메소드가 사용된 위 코드는 아래와 같이 JSX로도 작성될 수 있다.

//아래 요소들은 마치 html처럼 보이지만 사실은 JSX이다!
return (
    <div className="App">
  	<h1>Hi, I'm a React App</h1>
    </div>
);

자식요소나 형제요소가 추가될 때마다 React.createElement()메소드는 길어지지만, 그에 비해 JSX는 HTML가 유사한 모습을 가지고 있어 이해가 쉽고 과하게 코드가 길어지는 것을 방지할 수 있다.
즉, JSX는 JavaScript사용자들을 위한 문법적 설탕(syntactic sugar)인 것이다.
일반적으로 이와 같은 상황에서 겹겹이 괄호를 추가해야하는React.createElement()메소드보다 JSX가 사용되는 이유이다.


3. HTML !== JSX

JSX는 HTML의 모습을 하고 있지만 정확히 HTML의 문법을 그대로 적용할 수 있는 것은 아니다.
HTML에서는 태그의 클래스 속성을 class="Name"으로 지정해줄 수 있지만, JSX에서는 같은 속성을 className="Name" 으로 지정해줘야 한다.
말 그대로 JSX는 HTML이 아니기 때문!


4. 하나의 root 엘리먼트

JSX표현에서는 각 컴포넌트마다 오로지 하나의 root 엘리먼트를 가진다.

Each XML document has exactly one single root element. It encloses all the other elements and is therefore the sole parent element to all the other elements. ROOT elements are also called document elements.
-https://en.wikipedia.org/wiki/Root_element

class App extends Component {
  render() {
    return (
     <div className="App">
       <h1>Hi, I'm a React App</h1>  //첫번째 heading
       <p>This is really working!</p>
       <h1>Here's another heading</h1>  //두번째 heading 📍
     </div>
    );
  }
}

따라서 위와 같이 2개의 <h1>을 갖는 컴포넌트를 작성해도, 브라우저 상에 렌더링 되는 태그는 오직 첫번째 <h1>태그 하나이다.

<크롬 dev tool의 elements 탭>

<UI 스냅샷>

어디에도 두번째 <h2>는 보이지 않는다...!


5. Component 재사용하기

단순하게 원하는만큼의 컴포넌트명을 기재함으로써 컴포넌트를 재사용할 수 있다.
반복되어 기재된 횟수만큼 UI에 렌더링 된다.

< 코드 >

//App 컴포넌트
class App extends Component {
  render() {
    return (
     <div className="App">
       <h1>Hi, I'm a React App</h1>
       <p>This is really working!</p>
       <Person/> 📍
       <Person/> 📍
       <Person/> 📍
     </div>
    );
  }
}
-------------------------------------------------------
//Person 컴포넌트
const person = () => {
    return <p>I'm a Person!</p>
};

< UI >


6. JSX에서 표현식 사용하기

중괄호{}를 사용하면 JSX 에서 표현식을 첨부할 수 있다. (마치 template literal처럼)
괄호없이 표현식을 추가하면 text로 인식되지만, 중괄호를 감쌀 경우, 표현식의 결과값이 렌더링된다.

< 코드 >

const person = () => {
    return <p>I'm a Person and I am {Math.floor(Math.random() * 30)}years old!</p>
};

{Math.floor(Math.random() * 30)}의 결과가 UI에 렌더링된다.

< UI >


7. props로 component에 값 전달하기

props: 컴포넌트끼리 값을 전달하는 수단. html에서 attribute을 설정해주는 것과 같다.
class에서 props를 가지고 올 때는 this.props가 된다.

HTML 요소에 속성(attribute)을 설정해 주는 것처럼, JSX에서는 props로 컴포넌트에 사용자지정 속성(custom property)을 전달 할 수 있다.

< 코드 >

//App (parent)컴포넌트 : 사용자지정 속성으로 name 과 age 정보를 지정해주기
class App extends Component {
  render() {
    return (
     <div className="App">
       <h1>Hi, I'm a React App</h1>
       <p>This is really working!</p>
       <Person name="Hannah" age="22"/> 📍
       <Person name="Kyeonghee" age="50"/>📍
       <Person name="Sogeum" age="3"/>📍
     </div>
    );
  }
}
-------------------------------------------------------
//Person (자식)컴포넌트 : props로 값 전달하기
const person = (props) => {
    return <p>I'm {props.name} and I am {props.age} years old!</p> 
};

personprops객체를 인자로 전달받는다.
(인자명은 꼭 props가 아니더라도 자유롭게 지으면 된다.)
< UI >


8. props.children 으로 값 전달하기

{props.children}으로 열린 컴포넌트 태그(ex. <Person>)와 닫힌 컴포넌트 태그(ex. </Person>)사이의 값을 접근할 수 있다.
이 값은 일반 text뿐만 아니라 여러 줄의 리스트를 요소로 가지고 있는 <ul>이나 다른 컴포넌트 등 무엇이든 될 수 있다.

< 코드 >

//App 컴포넌트 : text로 값 지정
class App extends Component {
  render() {
    return (
     <div className="App">
       <h1>Hi, I'm a React App</h1>
       <p>This is really working!</p>
       <Person name="Hannah" age="22"/> 
       <Person name="Kyeonghee" age="50">Her hobbies: shopping</Person> 📍 //여기서는 일반 text를 전달한다.
       <Person name="Sogeum" age="3"/>
     </div>
    );
  }
}
-------------------------------------------------------
//Person 컴포넌트 : {props.children}
const person = (props) => {
    return (
    <div>
         <p>I'm {props.name} and I am {props.age} years old!</p>
         <p>{props.children}</p> 📍
    </div>
    )
};

< UI >


9. state로 컴포넌트 변경하기

state: 컴포넌트 내부에서 구성 요소를 변경하는 데 사용. state로 컴포넌트를 변경하면 UI 업데이트도 함께 진행된다.
오직 Class기반의 컴포넌트만이 state를 사용할 수 있다. (함수 기반의 컴포넌트에서 사용할 경우 직접변경이 불가능하다.)
props는 (함수 매개변수처럼) 다른 컴포넌트에 전달되는 반면, state는 (함수 내에 선언된 변수처럼) 같은 컴포넌트 안에서 사용된다.

props를 사용했는데도 state를 사용하는 이유는, 사용하는 쪽과 구현하는 쪽을 철저하게 분리시켜서 양쪽의 편의성을 각자 도모하는 것에 있다.
또한 props처럼 데이터를 사용자에게 노출되는 부분에 직접 적는 것이 아니라 state를 통해 참조함으로써,
사용자가 알 필요가 없는 데이터를 내부에서 은닉할 수 있게 된다.
캡슐화를 통해 코드를 리펙토링 하는 것이 좋은 사용성을 만드는 핵심이기 때문!!

//state 예시
class App extends Component {
  state = { 📍
    persons: [
      {name: 'Hannah', age: 22},
      {name: 'Kyeonghee', age: 50},
      {name: 'Sogeum', age: 3}
    ]
  }

  render() {
    return (
    //내용생략
    );
  }
}

10. JSX에서 이벤트 사용하기

예를 들어 Switch Name 버튼에 클릭이벤트를 걸고 싶다면, onClick={this.콜백함수명} 속성을 아래와 같이 추가해줄 수 있다.

< 코드 >

class App extends Component {
  //handler라는 이름을 붙여주면 이벤트로 호출되는 함수임을 직관적으로 알 수 있기 때문에 이렇게 짓는 것이 컨벤션
  switchNameHandler = () => {
    console.log("Was clicked!");📍
  }

  render() {
    return (
     <div className="App">
       <h1>Hi, I'm a React App</h1>
       <p>This is really working!</p>
       <button onClick={this.switchNameHandler}>Switch Name</button> 📍
       <Person name={this.state.persons[0].name} age={this.state.persons[0].age}/>
       <Person name={this.state.persons[1].name} age={this.state.persons[1].age}>Her hobbies: shopping</Person>
       <Person name={this.state.persons[2].name} age={this.state.persons[2].age}/>
     </div>
    );
  }
}

< UI >

더 많은 React Event 보기


11. setState() 사용하기

setState()비동기함수로, 이벤트 콜백함수에서 state 요소의 값을 동적으로 바꾸는 데에도 사용할 수 있다.
React에서는 단순히 값을 재할당 해주는 것으로 state 값이 바뀌지 않는다.
DON'T ➡️ this.state.persons[0].name = "Gina";this.state.persons[0].name의 값을 재할당 해주어도, 새로운 값이 렌더링 되지 않는다.
따라서 이 때에는 setState()를 사용해야 하는데, setState()DOM에 이미 렌더링 되어있는 코드와 새로 렌더링 하게 될 코드를 비교해 업데이트가 되어야 하는 부분을 분석한다. 그리고 재차 렌더링하여 변경된 부분들을 업데이트한다.

< 코드 >

class App extends Component {
  state = {
    persons: [
      {name: 'Hannah', age: 22},
      {name: 'Kyeonghee', age: 50},
      {name: 'Sogeum', age: 3}
    ],
    otherState: 'Something random'
  }

  switchNameHandler = () => {
    //React에서 무엇이 바뀌었는지 스스로 감지해서 업데이트를 한다.
    this.setState({ 📍
      persons: [
        {name: 'Gina', age: 30}, 📍 //이름과 나이를 바꿨다. Hannah -> Gina ; 22 -> 30
        {name: 'Kyeonghee', age: 50},
        {name: 'Sogeum', age: 4} 📍//나이를 바꿨다. 3 -> 4
      ]
    })
  }

  render() {
    return (
     <div className="App">
       <h1>Hi, I'm a React App</h1>
       <p>This is really working!</p>
       <button onClick={this.switchNameHandler}>Switch Name</button> 📍
       <Person name={this.state.persons[0].name} age={this.state.persons[0].age}/>
       <Person name={this.state.persons[1].name} age={this.state.persons[1].age}>Her hobbies: shopping</Person>
       <Person name={this.state.persons[2].name} age={this.state.persons[2].age}/>
     </div>
    );
  }
}

< UI >
클릭 전

클릭 후


Reference

https://www.udemy.com/course/react-the-complete-guide-incl-redux/learn/lecture/8090858#overview
https://velog.io/@hidaehyunlee/React-%EC%BB%B4%ED%8F%AC%EB%84%8C%ED%8A%B8%EC%9D%98-Props
https://velog.io/@hidaehyunlee/React-State-%EB%9E%80

profile
프린이의 코묻은 코드가 쌓이는 공간

0개의 댓글