Nomad Kim 2021. 1. 1. 01:24

Must know concepts

  • JSX 문법을 도입하게 된 이유가 무엇일까요? 어떤 장점이 있나요?
  • JSX를 사용하지 않고 React를 사용할 수도 있나요? (advanced)
  • JSX에 JavaScript 표현식을 쓰려면 어떤 방법으로 써야 하나요?
  • import / export 구문은 어떤 식으로 사용할 수 있나요?
  • DOM을 처음 배울 때 페이지 단위로 작업하는 방법과 비교해서, 컴포넌트 단위로 개발할 때의 장점은 무엇인가요?
  • 하나의 컴포넌트에서 여러 개의 엘리먼트를 리턴할 수도 있나요?
  • <Tweet>나의 새 트윗</Tweet>이라는 컴포넌트 사용 방법이 있다고 가정할 때, 컴포넌트 내에서 나의 새 트윗이라는 문자열은 어떻게 접근할 수 있나요?
  • props를 다룰 때에 지켜야 하는 엄격한 규칙이 하나 있습니다. 무엇인가요?
  • props와 state의 차이점은 무엇인가요?
  • 상태를 변경할 때 사용되는 this.setState는 어떻게 사용하나요?
    • 직접 this.state를 할당하거나, this.state의 키값을 수정하면 안되는 이유는 무엇인가요? 왜 꼭 this.setState를 사용해야만 할까요?
  • React에서 이벤트를 처리할 때에 HTML에서와 다른 특징은 무엇인가요?
  • 이벤트 처리시, 이벤트 핸들러를 다음과 같이 this 바인딩을 해줘야 하는 이유가 무엇인가요?

 

JSX 문법? 도입이유 장점

JSX는 함수 호출과 객체 생성을 위한 문법적 편의를 제공하는 자바스크립트의 확장으로, 특히 React.createElement() 호출을 반복해야 하는 불편을 해소한다. 템플릿 엔진이나 HTML처럼 보일 수도 있지만 그렇지 않다. JSX는 React 엘리먼트를 생성하면서 자바스크립트의 모든 기능을 쓸 수 있도록 도와준다.

JSX 없이 React 사용하기

JSX 사용

class Hello extends React.Component {
  render() {
    return <div>Hello {this.props.toWhat}</div>;
  }
}

ReactDOM.render(
  <Hello toWhat="World" />,
  document.getElementById('root')
);

JSX 미사용

긴 버전
class Hello extends React.Component {
  render() {
    return React.createElement('div', null, `Hello ${this.props.toWhat}`);
  }
}

ReactDOM.render(
  React.createElement(Hello, {toWhat: 'World'}, null),
  document.getElementById('root')
);
짧은 버전 
const e = React.createElement;

ReactDOM.render(
  e('div', null, 'Hello World'),
  document.getElementById('root')
);

JSX에 JavaScript 표현식 사용하기

 

JSX의 중괄호 안에는 유효한 모든 JavaScript 표현식을 넣을 수 있습니다.

예를 들어 2 + 2, user.firstName 또는 formatName(user) 등은 모두 유효한 JavaScript 표현식입니다.

function getGreeting(user) {
  if (user) {
    return <h1>Hello, {user.firstName}!</h1>;  }
  return <h1>Hello, Stranger.</h1>;}

function formatName(user) {
  return user.firstName + ' ' + user.lastName;
}

const user = {
  firstName: 'Harper',
  lastName: 'Perez',
};

const element = getGreeting(user);

ReactDOM.render(element, document.getElementById('root'));

import / export 구문은 어떤 식으로 사용할 수 있나요?

App.js

import React from "react";
import "./styles.css";

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

index.js

import React from "react";
import ReactDOM from "react-dom";

import App from "./App";

const rootElement = document.getElementById("root");
ReactDOM.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
  rootElement
);

 

디폴트 와 구조분해 할당으로 받을 수 있다.

 

Module.exports 와 exports 의 차이는 뭘까?

 

State와 Props의 차이점 또는 State를 사용하는 이유?

데이터의 은닉화.

 

1) State: 변할 수 있다.

class App extends Component {
  constructor(props) {
    super(props);
      this.state={
      user:{name:'kim',age:'secret!'}
    }
  }
  render() {
    return (
      	<div className="App">
        <singleTwittler 
        	name={this.state.user.name} 
    		age={this.state.user.age}>
        </singleTwittler>
      </div>
    );
  }
}

2) props: 변할 수 없다.

class App extends Component {
  render() {
    return (
      	<div className="App">
        <singleTwittler 
        	name='kim' 
    		age='secret!'>
        </singleTwittler>
      </div>
    );
  }
}

화면에 출력되는 내용은 완전히 똑같지만, props 데이터를 사용자에게 노출되는 부분에 직접 적는 것이 아니라 State를 통해 참조한다. 사용자가 알 필요가 없는 데이터를 내부에서 은닉할 수 있기 때문에 캡슐화를 통해 코드를 리펙토링 하여 사용성을 높일 수 있습니다.

 

컴포넌트 단위로 개발할 때의 장점은 무엇인가요?

화면 view단을 구현하기 위한 최소단위로 재사용가능하고, 유지보수가 용이합니다.

컴포넌트를 통하여 UI를 재사용 가능한 개별적인 여러 조각으로 나누고, 각 조각을 개별적으로 살펴볼 수 있어서 재사용이라는 측면에서 용이하고, 조각별로 구분하여 직관적으로 파악할 수 있다는 것이 장점이다.

컴포넌트 끼리 영향을 주지 않기 때문에 테스트하기에도 좋다.

 

하나의 컴포넌트에서 여러 개의 엘리먼트를 리턴할 수도 있나요?

fragment를 통하여 가능하고 또한 단축 문법인 빈 태그로도 가능하다, 허나 fragment에 key가 존재한다면 react.fragment를 명시적으로 선언 해야 한다.

 

<Tweet>나의 새 트윗</Tweet>이라는 컴포넌트 사용 방법이 있다고 가정할 때, 컴포넌트 내에서 나의 새 트윗이라는 문자열은 어떻게 접근할 수 있나요?

props.children 혹은 props인자에 {children}을 주게 된다면 props를 제외하고 children만 작성하여 접근할 수 있다.

 

 

props를 다룰 때에 지켜야 하는 엄격한 규칙이 하나 있습니다. 무엇인가요?

모든 react컴포넌트는 자신의 props를 다룰 때, 반드시 순수 함수처럼 동작해야 한다. 순수 함수란, 입력값을 바꾸려 하지 않고 항상 동일한 입력값에 대해 동일한 결과를 반환하는 것이다.

외부 영향에 의해 변경되면 안되고 읽는 용도로만 사용해야 한다.

 

외부 인자에 의해 영향을 받는다.

 

props와 state의 차이점은 무엇인가요?

props는 외부에서부터 전달 받은 값이고, state는 내부에서 변하는 값이다.

상태를 변경할 때 사용되는 this.setState는 어떻게 사용하나요?

  • 직접 this.state를 할당하거나, this.state의 키값을 수정하면 안되는 이유는 무엇인가요? 왜 꼭 this.setState를 사용해야만 할까요?

컴포넌트에 있는 state객체에 대한 상태를 업데이트 실행합니다. state가 변경되면, 컴포넌트는 리렌더링됩니다.

setState 가 일어나면 rerender를 한다.

React에서 이벤트를 처리할 때에 HTML에서와 다른 특징은 무엇인가요?

react는 DOM 엘리먼트가 생성된 후 리스너를 추가하기 위해 addEventListener를 호출할 필요가 없다.

이벤트 처리시, 이벤트 핸들러를 다음과 같이 this 바인딩을 해줘야 하는 이유가 무엇인가요?

this.handleClick은 바인딩하지 않고 onClick으로 전달하면, 함수 호출시 undefined가 호출되기때문에,

this를 명시적으로 한정지어야 제대로 인식을 하고 함수가 실행된다. 바인드 해야 this를 알 수 있다.

 

arrow function 을 사용한다면 this바인딩 필요없다.


React 주요 개념

1. Hello World

2. JSX 소개

 

JSX란?
JavaScript XML 라 하며 JavaScript를 확장한 문법입니다. 
JSX는 React “엘리먼트(element)” 를 생성합니다.

  • React에서는 이벤트가 처리되는 방식, 시간에 따라 state가 변하는 방식, 화면에 표시하기 위해 데이터가 준비되는 방식 등 렌더링 로직이 본질적으로 다른 UI 로직과 연결됩니다.
  • React는 “컴포넌트”라고 부르는 느슨하게 연결된 유닛으로 관심사를 분리합니다.
  • JSX의 중괄호 안에는 유효한 모든 JavaScript 표현식을 넣을 수 있습니다. 예를 들어 2 + 2, user.firstName 또는 formatName(user) 등은 모두 유효한 JavaScript 표현식입니다.
  • 컴파일이 끝나면, JSX 표현식이 정규 JavaScript 함수 호출이 되고 JavaScript 객체로 인식됩니다. 즉, JSX를 if 구문 및 for loop 안에 사용하고, 변수에 할당하고, 인자로서 받아들이고, 함수로부터 반환할 수 있습니다.

3. 엘리먼트 렌더링

 

  • 브라우저 DOM 엘리먼트와 달리 React 엘리먼트는 일반 객체이며(plain object) 쉽게 생성할 수 있습니다.
  • React DOM은 React 엘리먼트와 일치하도록 DOM을 업데이트합니다.
  • React 엘리먼트는 불변객체입니다. 엘리먼트를 생성한 이후에는 해당 엘리먼트의 자식이나 속성을 변경할 수 없습니다. 

렌더링 된 엘리먼트 업데이트하기

 

  1. setInterval 이용하여 tick 함수를 1초마다 실행
  2. ReactDOM.render 가 호출됨
  3. element 안에 있는 {new Date().toLocaleTimeString()} 이 업데이트 된 값을 포함한 element가 root 노드의 children으로 들어가 렌더됨. 

매초 전체 UI를 다시 그리도록 엘리먼트를 만들었지만 React DOM은 내용이 변경된 텍스트 노드만 업데이트

4. Component 와 Props

 

컴포넌트 렌더링

  • React가 사용자 정의 컴포넌트로 작성한 엘리먼트를 발견하면 JSX 어트리뷰트와 자식을 해당 컴포넌트에 단일 객체(props)로 전달합니다.
  • 컴포넌트의 이름은 항상 대문자로 시작합니다. 

컴포넌트 합성

  • 컴포넌트는 자신의 출력에 다른 컴포넌트를 참조할 수 있습니다. React 앱에서는 버튼, 폼, 다이얼로그, 화면 등의 모든 것들이 흔히 컴포넌트로 표현됩니다.

컴포넌트 추출

  • 재사용 가능한 컴포넌트를 만들어 놓는 것은 더 큰 앱에서 작업할 때 두각을 나타냅니다. UI 일부가 여러 번 사용되거나 (Button, Panel, Avatar), UI 일부가 자체적으로 복잡한 (App, FeedStory, Comment) 경우에는 별도의 컴포넌트로 만드는 게 좋습니다.

코드: codepen.io/pen?editors=0010

해석:

 

  • Props는 읽기 전용 이므로, 함수 컴포넌트나 클래스 컴포넌트 모두 컴포넌트의 자체 props를 수정해서는 안 됩니다.

5. State and Lifecycle

State는 props와 유사하지만, 비공개이며 컴포넌트에 의해 완전히 제어됩니다.

클래스 컴포넌트는 항상 props로 기본 constructor를 호출해야 합니다.

 

State?

컴포넌트 내부에서 변경될 수 있는 값.

state 값을 변경하려고 한다면, setState 메서드를 이용합니다.

그리고 setState 메서드를 사용해서 state값을 변경하면, render()함수가 다시 실행됩니다.

 

Lifecycle이란?

component의 생명주기를 말하며, 페이지에 렌더링 되기 전 준비과정에서 시작해서 페이지에서 사라질 때 끝이 납니다.

즉, 생명주기를 이용하여 많은 컴포넌트가 있는 애플리케이션에서 컴포넌트가 삭제될 때 해당 컴포넌트가 사용 중이던 리소스를 확보할 수 있습니다.

 

Component가 생성될 때 => Mounting,  Component가 제거될 때=> Unmounting

자주 사용되는 생명주기 메서드(진하게 표시)

 

1) 마운트

: 컴포넌트의 인스턴스가 생성되어 DOM 상에 삽입될 때에 순서대로 호출됩니다.

  • constructor(): 메서드를 바인딩하거나 state를 초기화하는 작업이 없다면, 해당 React 컴포넌트에는 생성자를 구현하지 않아도 됩니다.
  • render(): 클래스 컴포넌트에서 반드시 구현돼야하는 유일한 메서드입니다.
  • componentDidMount(): 컴포넌트(출력물)가 render된 직후 바로 실행됩니다. 여기서는 외부라이브러리 연동, Ajax, GraphQL, axios 등 컴포넌트에 필요한 데이터 요청, 스크롤 설정 등의 DOM에 관련된 작업을 수행합니다. 데이터 구독을 설정하기 좋은 위치 입니다.
  • static getDerivedStateFromProps

 

2) 업데이트

: props 또는 state가 변경되면 갱신이 발생합니다. 아래 메서드들은 컴포넌트가 다시 렌더링될 때 순서대로 호출됩니다.

 

  • render()
  • componentDidUpdate(): 갱신이 일어난 직후에 호출됩니다. 이 메서드는 최초 렌더링에서는 호출되지 않습니다. 이전과 현재의 props를 비교하여 네트워크 요청을 보내는 작업도 이 메서드에서 이루어지면 됩니다.
  • static getDerivedStateFromProps()
  • shouldComponentUpdate()
  • getSnapshotBeforeUpdate()

 

3) 마운트 해제

: 컴포넌트가 DOM 상에서 제거될 때에 호출됩니다.

  • componentWillUnmount(): 컴포넌트가 마운트 해제되어 제거되기 직전에 호출됩니다. 여기에서는 사용하지 않는 timer나 네트워크 요청 취소 같은 자원해제 작업을 합니다.  그리고 컴포넌트가 다시 re-rendering될 일이 없기 때문에 setState를 사용할 수 없습니다. 컴포넌트가 unmounted되면 다시 mounted될 수 없습니다.

 

4) 오류 처리

: 자식 컴포넌트를 렌더링하거나, 자식 컴포넌트가 생명주기 메서드를 호출하거나, 또는 자식 컴포넌트가 생성자 메서드를 호출하는 과정에서 오류가 발생했을 때에 호출됩니다.

  • static getDerivedStateFromError()
  • componentDidCatch()

기타 API

이 외에도 컴포넌트는 몇몇 API를 제공합니다.

class 프로퍼티

인스턴스 프로퍼티

 

 

class Clock extends React.Component {
  constructor(props) { //2. 먼저 React는 Clock 컴포넌트의 constructor를 호출
    super(props);
    this.state = {date: new Date()}; //3. 현재 시각이 포함된 객체로 this.state를 초기화
  }

  componentDidMount() { //6. Clock 출력값이 DOM에 삽입되면, React는 componentDidMount() 생명주기 메서드를 호출한다.
  //그 안에서 Clock 컴포넌트는 매초 컴포넌트의 tick() 메서드를 호출하기 위한 타이머를 설정하도록 브라우저에 요청한다.
    this.timerID = setInterval(
      () => this.tick(), // 7. 매초 브라우저가 tick() 메서드를 호출한다. 
      1000
    );
  }

  componentWillUnmount() {//10. Clock 컴포넌트가 DOM으로부터 한 번이라도 삭제된 적이 있다면 React는 타이머를 멈추기 위해 componentWillUnmount() 생명주기 메서드를 호출한다. 
    clearInterval(this.timerID);
  }

  tick() {//8.그 안에서 Clock 컴포넌트는 setState()에 현재 시각을 포함하는 객체를 호출하면서 UI 업데이트를 진행한다.   
    this.setState({//setState() 호출 덕분에 React는 state가 변경된 것을 인지하고 화면에 표시될 내용을 알아내기 위해 render() 메서드를 다시 호출
      date: new Date()
    });
  }

//9. 이 때 render() 메서드 안의 this.state.date가 달라지고 렌더링 출력값은 업데이트된 시각을 포함하고. React는 이에 따라 DOM을 업데이트한다.
  render() { //4. React는 Clock 컴포넌트의 render() 메서드를 호출하고
    return ( // 5. 아래 내용 즉, React는 화면에 표시되어야 할 내용을 알게 된다. 
      <div> 
        <h1>Hello, world!</h1>
        <h2>It is {this.state.date.toLocaleTimeString()}.</h2> //6.그 다음 React는 Clock의 렌더링 출력값을 일치시키기 위해 DOM을 업데이트한다.  
      </div>
    );
  }
}

ReactDOM.render(//1. <Clock />가 ReactDOM.render()로 전달. 
  <Clock />, 
  document.getElementById('root')
);

아래와 같이 실행되는 것을 확인할 수 있습니다.

결과 화면

 

State 주의해야 할 점.

  • 직접 State를 수정하지 않습니다.
  • State 업데이트는 비동기적일 수 있습니다.
  • State 업데이트는 병합됩니다.

6. 이벤트 처리하기

 

JavaScript에서 클래스 메서드는 기본적으로 바인딩되어 있지 않기 때문에 바인딩 없이 onClick에 전달하면, 함수가 실제 호출될 때 this는 undefined가 됩니다.

일반적으로 onClick={this.handleClick}과 같이 뒤에 ()를 사용하지 않고 메서드를 참조할 경우,

this.handClick.bind(this) 와 같이 해당 메서드를 바인딩 해야 합니다.

 

 

 

 

 

 

 

 

이 부분이 헷갈린다면 화살표 함수를 활용할 수 있습니다.

 

 

 

 

 

 

 

7. 조건부 렌더링

1) 논리 && 연산자로 if를 인라인 표현하는 방법

 

JavaScript에서 true && expression은 항상 expression으로 평가되고 false && expression은 항상 false로 평가됩니다.

따라서 && 뒤의 엘리먼트는 조건이 true일때 출력이 됩니다. 조건이 false라면 React는 무시합니다.

2) 삼항 연산자로 if-else 구문  인라인 표현하는 방법

8. 리스트와 Key

리스트의 각 항목에 key를 넣어야 한다는 경고

  • “key”는 엘리먼트 리스트를 만들 때 포함해야 하는 특수한 문자열 어트리뷰트입니다.
  • key는 React가 어떤 항목을 변경, 추가 또는 삭제할지 식별하는 것을 돕습니다.
  • key는 엘리먼트에 안정적인 고유성을 부여하기 위해 배열 내부의 엘리먼트에 지정해야 합니다.
  • 키는 주변 배열의 context에서만 의미가 있습니다. 즉 배열의 엘리먼트가 key 를 가져야 합니다.
  • 이상적으로, Key는 post.id와 같이 데이터에서 사용되는 유일하고 안정적인 식별자를 사용하는 것이 좋습니다.

9. 폼

10. State 끌어 올리기(다른 글에서 정리)

11. 합성 VS 상속

12. React 로 사고하기

 

출처:  ko.reactjs.org/

libertegrace.tistory.com/

 

Grace's Study Blog

긍정적인 마음가짐을 가진 도전과 활발한 커뮤니케이션을 동반한 협력의 힘을 믿고 있고, 그런 사람이 되려고 합니다. =========================== Github👩🏻‍💻: https://github.com/Gracechung-sw ==============

libertegrace.tistory.com

React를 구성하는 JavaScript 생태계

 

Create React App을 구성하고 있는 babel 및 webpack의 목적과 필요성을 이해할 수 있다.

Babel: Babel는 최신 사양의 자바스크립트 코드를 IE나 구형 브라우저에서도 동작하는 ES5 이하의 코드로 변환(트랜스파일링)할 수 있다. 

webpack: Webpack은 의존 관계에 있는 모듈들을 하나의 자바스크립트 파일로 번들링하는 모듈 번들러이다. Webpack을 사용하면 의존 모듈이 하나의 파일로 번들링되므로 별도의 모듈 로더가 필요없다. 그리고 다수의 자바스크립트 파일을 하나의 파일로 번들링하므로 html 파일에서 script 태그로 다수의 자바스크립트 파일을 로드해야 하는 번거로움도 사라진다.