본문 바로가기
Programming Step/React JS

REACT 공식 문서 정리

by eclipse7727 2021. 6. 20.

 

REACT 공식 문서 정리

목차

1. React를 배우는 이유

2. React를 배우기 전 기본 조건

3. JSX 표현식



1. React를 배우는 이유

웹 개발을 하게 될 때, 귀찮은 DOM 관리와 상태값 업데이트 관리를 최소화 한다.

기능 개발, 그리고 사용자 인터페이스를 구현하는 것에 집중할 수 있다.

지속해서 데이터가 변화하는 대규모 애플리케이션을 구축하기 위해 React가 제작됨. 

2. React를 배우기 전 기본 조건

HTML 및 CSS 에 대한 기본 지식.

Javascript 및 프로그램에 대한 기본 지식

DOM 에 대한 기본적인 이해.

ES6 구문 및 기능

Node.js 및 npm 설치

 

3. JSX 표현식

 

JavaScript를 확장한 문법이며 UI를 제작에 React와 함께 사용할 것을 권장한다.

JavaScript의 모든 기능이 포함되어 있다. 

JSX는 HTML문법을 사용해서 View를 구성할 수 있게 도와주는 자바스크립트 문법이다.

중괄호 안에 JavaScript 표현식을 넣을 수 있다.

JavaScript에 가깝기 때문에 HTML 속성과는 조금 다르다.

ex) HTML 속성 class JSX에서 className으로 사용된다.

카멜 표기법을 사용해서 나타낸다

JSX 삽입된 내용은 문자열로 변환 해주기 때문에 XSS 공격 방지가 가능하다.

const name = 'Josh Perez';
const element = <h1>Hello, {name}</h1>;

 

속성에 따옴표를 이용해 문자열 리터럴 사용 가능하다.

const e= <div idx="0"></div>;

 

중괄호를 사용하여 속성에 JavaScript 표현식을 삽입 할 수 있다.

const e = <img src={user.url}></img>;

 

React.CreateElement()함수로 JSX 객체를 생성 할 수 있다.

아래 두 코드는 같은 객체이다.

const element = (
  <h1 className="greeting">
    Hello, world!
  </h1>
);

 

const element = React.createElement(
  'h1',
  {className: 'greeting'},
  'Hello, world!'
);

 

4. Element 렌더링

 

4.1 element의 정의

Element는 컴포넌트의 구성요소이며 React  앱의 가장 작은 단위이다.

특정 부분만 리렌더링 할 수 있기에 효율적인 자원관리를 할 수있다.

위의 예시는 다음과 같은 일이 일어난다.

function Welcome(props) {
  return <h1>Hello, {props.name}</h1>;
}

const element = <Welcome name="Sara" />;
ReactDOM.render(
  element,
  document.getElementById('root')
);
  1. <Welcome name="Sara" /> 엘리먼트로 ReactDOM.render()를 호출한다.
  2. React는 {name: 'Sara'}를 props로 하여 Welcome 컴포넌트를 호출한다.
  3. Welcome 컴포넌트는 결과적으로 <h1>Hello, Sara</h1> 엘리먼트를 반환한다.
  4. React DOM은 <h1>Hello, Sara</h1> 엘리먼트와 일치하도록 DOM을 효율적으로 업데이트한다.

렌더링이라는 단어가 생소 할 때 브라우저 기초 지식의 렌더링 엔진을 참고하자.

 

4.2 렌더링된 Element 업데이트 하기

function tick() {
  const element = (
    <div>
      <h1>Hello, world!</h1>
      <h2>It is {new Date().toLocaleTimeString()}.</h2> // 리렌더링 부분
    </div>
  );
  ReactDOM.render(element, document.getElementById('root'));
}
setInterval(tick, 1000);

예시일 뿐 대부분의 react 앱은ReactDom.render를 한번만 호출한다.

setInterval() 콜백을 이용해 1초마다 render()함수를 호출한다.

1초마다 전체 렌더링을 다시 하지만,  매번 바뀌는 부분만 다시 렌더링 한다.

 

5. Component 와 Props

5.1 Component의 정의

컴포넌트의 제작 방법은 함수형과 클래스형으로 나누어져 있다.

컴포넌트를 쓰는 이유중 하나는 재사용을 편하게 하기 위함이다.

App 최상위 컴포넌트 아래에 여러 사용자 정의 컴포넌트가 존재한다.

클래스형 보다는 함수형이 간결하게 사용할 수 있다.

 

5.2 props의 정의

  • React가 JSX 속성 또는 자식을 해당 컴포넌트에 단일 객체로 전달하는데 이 객체를 Props라 한다.
  • 주의사항 : props는 읽기 전용이므로 수정 X

ex) 함수 컴포넌트와 클래스 컴포넌트 예시

// 함수형
function Welcome(props) {
  return <h1>Hello, {props.name}</h1>;
}
// 클래스형
class Welcome extends React.Component {
  render() {
    return <h1>Hello, {this.props.name}</h1>;
  }
}
  • 위의 함수와 클래스의 출력은 동일하다. 
  • 데이터를 가진 하나의 “props” 객체 인자를 받은 후 React Element를 반환 한다.

5.3 컴포넌트의 재사용

function Welcome(props) {
  return <h1>Hello, {props.name}</h1>;
}
function App(){
  return (
    <div>
     <Welcome name="Sara" />
     <Welcome name="Cahal" />
   </div>
  );
}
  • 위처럼 App 안에 Welcome 컴포넌트의 내용을 재사용 할 수있다.

 

5.4 사용자 정의 컴포넌트

  • 말 그대로 사용자가 정의한 컴포넌트이다.
  • function Welcome(props) {
      return <h1>Hello, {props.name}</h1>;
    }
    const element = <Welcome name="Sara" />; // 사용자 정의 컴포넌트 부분임.

주의사항 : 컴포넌트의 이름은 항상 대문자로 시작함.

  • 컴포넌트 재사용은 객체 재사용 하는것과 비슷함. 재사용성 UP

6. State 와 생명주기

6.1 State의 정의

State는 React Component Class의 instance이다.

Component의 동작을 제어하는 관측 할 수있는 속성 집합의 개체로 정의 된다.

Component의 State는 Lifetime에 따라 변경될 수 있는 정보를 보유한 객체이다.

 

6.2 Props와 State의 차이.

Props는 변하지 않는 속성을 가지고 있다.

State는 시간이 지남에 따라 변경 될 수 있는 데이터를 가지고 변경 후 동작을 제어하는데 사용되는 관찰 가능한 개체이다.

State는 컴포넌트 안에서만 사용할 수 있는 반면 Props는 제한이 없다.

 

6.3 생명주기(Life Cycle)

  • 클래스 컴포넌트와 함수형 컴포넌트의 생명주기는 동일하게 동작한다.

 

6.3.1 리액트 컴포넌트 라이프 사이클 4단계

  1. Initialization : props와 state를 초기화 한다.

 

  1. Mounting :  render() 메서드에서 반환 한 JSX를 렌더링 하는 단계이다.
  • componentDidMount()
  • DOM에 마운트 된 후(render() 함수 뒤에) 호출된다.

 

  1. Update : State 또는 Props가 갱신되면 발생한다.
  • shouldComponentUpdate(nextProps, nextState)
  • 현재 State 또는 Props의 변화가 컴포넌트 출력 결과에 영향을 미치는지 여부를 React가 알 수 있다. 기본 동작은 매 State 변화마다 리렌더링을 수행하는 것이다.
  • componentDidUpdate(prevProps, prevState, snapshot)
  • State가 업데이트 된 후에 실행된다.

 

  1. Unmounting : Dom에서 컴포넌트를 마운트 해제하는 단계이자, 라이프 사이클의 마지막 단계 
  • componentWillUnmount() : 컴포넌트가 DOM 상에서 제거될 때 호출된다.

 

class Clock extends React.Component {
  constructor(props) {
    super(props);
    this.state = {date: new Date()};
  }

componentDidMount() { // 마운트 후에 interval 함수로 1초마다 반복 설정.
this.timerID = setInterval(
  () => this.tick(),
      1000
  );
}

componentWillUnmount() { // 언마운트시 invterval 함수 해제
  clearInterval(this.timerID);
}

tick() { // interval 함수가 1초마다 setState를 갱신하게 하여 리렌더링 함.  
  this.setState({
      date: new Date()
    });
  }

  render() {
    return (
      <div>
        <h1>Hello, world!</h1>
        <h2>It is {this.state.date.toLocaleTimeString()}.</h2>
      </div>
    );
  }
}

ReactDOM.render(
  <Clock />,
  document.getElementById('root')
);


주의사항 : state는 setState로만 수정해야 한다. 

직접적으로 수정시 리렌더링 하지 않는다.

state 업데이트는 비동기적일 수도 있다.

state값을 인자로 가져와서 작업함으로써 비동기 상황을 방지한다.

// ERROR 코드
this.setState({
  counter: this.state.counter + this.props.increment, // 예상한 값과 달라질 수 있음.
});
// SUCCESS 코드
this.setState((state, props) => ({
  counter: state.counter + props.increment
}));

[2021-03-23]

7. 이벤트 처리하기

7.1 이벤트 처리방식의 차이

React 엘리먼트에서 이벤트를 처리하는 방식은 DOM 엘리먼트에서 이벤트를 처리하는 방식과 비슷하며, 차이는 다음과 같다.

  1. React의 이벤트는 소문자 대신 캐멀 케이스(camelCase)를 사용한다.
  2. JSX를 사용하여 문자열이 아닌 함수로 이벤트 핸들러를 전달한다.

<HTML에서의 코드>

<button onclick="activateLasers()"> // 버튼이 눌렸을 때 해당 함수 작동
  Activate Lasers
</button>

<React 에서의 코드>

<button onClick={activateLasers}>
Activate Lasers
</button>
  1. React에서는 false를 반환해도 기본 동작을 방지할 수 없습니다. 반드시 preventDefault를 명시적으로 호출해야 한다.

(return false; : 태그의 기본 속성을 무시한다. 기능을 직접 구현할 때 사용한다)

 

function ActionLink() {

function handleClick(e) {
  e.preventDefault(); // 클릭 차단, 입력 차단등 이벤트가 취소됨
  console.log('The link was clicked.');
}

  return (

  <a href="#" onClick={handleClick}> // 클릭시 handleClick 함수를 실행
    Click me
    </a>
  );
}

 

React를 사용할 때 DOM 엘리먼트가 생성된 후 리스너를 추가하기 위해 addEventListener를 호출할 필요가 없다. 대신, 엘리먼트가 처음 렌더링될 때 리스너를 제공하면 된다.

 

class Toggle extends React.Component {
  constructor(props) {
    super(props);
    this.state = {isToggleOn: true};

  // 콜백에서 this가 작동하려면 아래와 같이 바인딩 해주어야 한다.
  this.handleClick = this.handleClick.bind(this);
}


handleClick() {
  this.setState(state => ({
    isToggleOn: !state.isToggleOn //state의 isToggleOn의 값을 반대로 바꾼다.
  }));
}

  render() {
    return (
    <button onClick={this.handleClick}>
      {this.state.isToggleOn ? 'ON' : 'OFF'}
      </button>
    );
  }
}

ReactDOM.render(
  <Toggle />,
  document.getElementById('root')
);

 

7.2 bind

7.2.1 React의 bind

Javascript에서 클래스 메서드는 기본적으로 바인딩 되어 있지 않다.

this.handleClick을 바인딩하지 않고 onClick에 전달 하였다면 함수가 실제 호출될 때 this는 undefined가 된다. (bind를 처음 들어본다면)

react만의 특수한 동작이 아니며 javascript에서 함수가 작동하는 방식중 일부이다.

onClick={this.handleClick} 과 같이 () 를 사용하지 않고 메서드를 참조할 경우 바인드는 필수이다.

 

7.2.2 arrow function 과 bind

7.2.2.1 화살표 함수 정의

먼저 화살표 함수란 함수 표현식을 간결한 문법으로 만드는 것입니다.

class LoggingButton extends React.Component {
  handleClick() {
    console.log('this is:', this);
  }

  render() {

  // ‘this’가 handleClick 내에서 바인딩되도록 한다.
  return (
    <button onClick={() => this.handleClick()}>
      Click me
      </button>
    );
  }
}
let func = function(arg1, arg2, ...argN) {
  return expression;
};

위와 같은 일반적인 함수를 화살표 함수로 바꾸면 아래와 같습니다.

let func = (arg1, arg2, ...argN) => expression

직관적이고 코드가 짧아지는 장점이 있습니다.

class LoggingButton extends React.Component {
  handleClick() {
    console.log('this is:', this); // this를 출력함.
  }

  render() {

  // ‘this’가 handleClick 내에서 바인딩되도록 한다.
  return (
    <button onClick={() => this.handleClick()}> //
      Click me
      </button>
    );
  }
}

위의 코드의 문제점은 LoginButton이 렌더링 될 때마다 다른 콜백이 생성된다는 것이다. 대부분은 문제가 되지 않으나, 콜백이 하위 컴포넌트에 props로 전달된다면 그 컴포넌트들은 추가로 리렌더링 될 수 있다. 이러한 문제를 피하고자 생성자안에서 바인딩 하거나 클래스 필드 문법을 사용하는 것을 권장한다. 

화살표 함수는 뒤에 나올 react hook에 자주 사용된다.


7.2.2.3 화살표 함수 주의점

<주의사항> IE와는 호환이 되지 않습니다.



8. 조건부 렌더링

8.1 조건부 렌더링

React에서는 원하는 동작을 캡슐화하는 컴포넌트를 만들 수 있다. 이렇게 하면 어플리케이션의 상태에 따라서 컴포넌트 중 몇 개만을 렌더링 할 수 있다.

예시는 아래와 같다.   props.isLoggedIn 에 따라서 다른 인사말을 렌더링 한다. 

 

function UserGreeting(props) { // 사용자에게 인사
  return <h1>Welcome back!</h1>; 
}

function GuestGreeting(props) { // 게스트에게 인사
  return <h1>Please sign up.</h1>;
}

function Greeting(props) {
  const isLoggedIn = props.isLoggedIn;

if (isLoggedIn) { 
   // props.isLoggedIn 값에 따라 유저 또는 게스트 컴포넌트를 사용함.
  return <UserGreeting />;
}
return <GuestGreeting />;
}

ReactDOM.render(
  // Try changing to isLoggedIn={true}:
<Greeting isLoggedIn={false} />,document.getElementById('root')
);

 

위의 코드처럼 사용하는것도 좋지만 출력의 다른 부분을 변경하지 않고 컴포넌트의 일부를 조건부로 렌더링할 수도 있습니다. (렌더링 최적화)

class LoginControl extends React.Component {
  constructor(props) { // 생성자
    super(props);
    this.handleLoginClick = this.handleLoginClick.bind(this); // 바인드
    this.handleLogoutClick = this.handleLogoutClick.bind(this);
    this.state = {isLoggedIn: false};
  }

 handleLoginClick() {
    this.setState({isLoggedIn: true}); // state.isloggedIn을 true로 설정
  }

  handleLogoutClick() {
    this.setState({isLoggedIn: false}); // state.isloggedIn을 false로 설정
  }

  render() {
    const isLoggedIn = this.state.isLoggedIn; // 변수에 isLoggedIn 저장
    let button;

  if (isLoggedIn) {
    button = <LogoutButton onClick={this.handleLogoutClick} />;
     // true일때 렌더링
  } else {
    button = <LoginButton onClick={this.handleLoginClick} />;
     // false일때 렌더링
  }

    return (
      <div>

      <Greeting isLoggedIn={isLoggedIn} />
      {button}
    </div>
    );
  }
}

ReactDOM.render(
  <LoginControl />,
  document.getElementById('root')
);



8.2 논리 && 연산자로 If를 인라인으로 표현하기

function Mailbox(props) {
  const unreadMessages = props.unreadMessages;
  return (
    <div>
      <h1>Hello!</h1>

    // true && expression == expression
    // false && expression == false
     // unreadMessages의 배열 길이가 0보다 크다면 <h2> 태그 안에 있는 내용 출력
    {unreadMessages.length > 0 && 
      <h2>
        You have {unreadMessages.length} unread messages.
      </h2>
    }
  </div>
  );
}

const messages = ['React', 'Re: React', 'Re:Re: React'];
ReactDOM.render(
  // Mailbox 컴포넌트를 사용 인자로 messages 배열을 넘겨줌
  <Mailbox unreadMessages=



 

8.3 조건부 연산자로 If-Else구문 인라인으로 표현하기

엘리먼트 조건부로 렌더링하는 다른 방법은 3항 연산자인 condition ? true : false 를 사용하는 것이다.

render() {
  const isLoggedIn = this.state.isLoggedIn;
  return (
    <div>

    {isLoggedIn
      ? <LogoutButton onClick={this.handleLogoutClick} /> // 참일 때 로그아웃
      : <LoginButton onClick={this.handleLoginClick} /> // 거짓 일 때 로그인
    }

  </div>
);
}




8.4 컴포넌트가 렌더링하는 것을 막기

특정 컴포넌트가 렌더링되는것을 막고 싶다면 렌더링 결과를 출력하는 대신 null 값을 반환하면 해결할 수 있다.

 

function WarningBanner(props) {

if (!props.warn) {
  return null; 
   // warningBanner 컴포넌트의 props가 거짓이면 null 값을 반환하고 렌더링 X
   // 참이면 Warning을 렌더링함
}

  return (
    <div className="warning">
      Warning!
    </div>
  );
}

class Page extends React.Component {
  constructor(props) {
    super(props);
    this.state = {showWarning: true}; // 초기 showWarning값은 true
    this.handleToggleClick = this.handleToggleClick.bind(this); // 바인드
  }

  handleToggleClick() {
    this.setState(state => ({
      showWarning: !state.showWarning //함수호출시 showWarning값을 반대로 바꿈
    }));
  }

  render() {
    return (
      <div>

      <WarningBanner warn={this.state.showWarning} /> 
       // 참 거짓에 따라 렌더링
      <button onClick={this.handleToggleClick}>
       // 버튼 클릭시 handleToggleClick 함수를 호출함
          {this.state.showWarning ? 'Hide' : 'Show'}
          // showWarning 값에 따라 hide or show 출력
        </button>
      </div>
    );
  }
}

ReactDOM.render(
  <Page />, // page컴포넌트 호출
  document.getElementById('root')
);

 

9. 리스트와 Key

9.1 map()의 정의

먼저 Javascript에서 리스트를 어떻게 변환 하는지 살펴보자.

아래는 map() 함수를 이용하여 numbers 배열의 값을 두 배로 만든 후 map()에서 반환하는 새 배열 doubled 변수에 할당하고 로그를 확인하는 코드이다.

const numbers = [1, 2, 3, 4, 5]; // 배열 생성
const doubled = numbers.map((number) => number * 2); 
// 배열 횟수만큼 콜백 함수를 호출해서 돌리고 결과를 배열로 반환함.
console.log(doubled); // 출력 결과는 [2, 4, 6, 8, 10]

 

map()은 배열의 각 요소에 대해 제공된 callback 함수를 순서대로 호출하고 결과로 부터 새 배열을 구성하여 반환함. 값이 할당(undefined 포함) 된 배열의 인덱스에 대해서만 호출된다.

call by value 방식으로 값을 가져온다.

map()에 대해 더 자세히 알고 싶다면 (클릭)




9.2 여러개의 컴포넌트 렌더링

9.1에서 배운 map() 사용하면 여러개의 컴포넌트를 렌더링 하기 쉽다.

const numbers = [1, 2, 3, 4, 5];
const listItems = numbers.map((number) =>
<li>{number}</li>
);
// 출력은 아래와 같다.
<li>{1}</li>
<li>{2}</li>
<li>{3}</li>
<li>{4}</li>
<li>{5}</li>

 

function NumberList(props) {
  const numbers = props.numbers;

const listItems = numbers.map((number) =>
  <li>{number}</li>
);
return (
  <ul>{listItems}</ul>
);
}
// numberList 컴포넌트의 반환 값은 다음과 같다
//<ul>
//  <li>{1}</li>
//  <li>{2}</li>
//  <li>{3}</li>
//  <li>{4}</li>
//  <li>{5}</li>
//</ul>
const numbers = [1, 2, 3, 4, 5];
ReactDOM.render(

<NumberList numbers={numbers} />,
document.getElementById('root')
);

 

9.3 기본 리스트 컴포넌트

위 코드를 돌려보면 아래와 같은 에러가 뜰 수 있다.

function NumberList(props) {
  const numbers = props.numbers;
  const listItems = numbers.map((number) =>

  <li key={number.toString()}> 
   // 콜백 함수인자인 number의 문자를 key 속성으로 입력
    {number}
    </li>
  );
  return (
    <ul>{listItems}</ul>
  );
}

const numbers = [1, 2, 3, 4, 5];
ReactDOM.render(
  <NumberList numbers={numbers} />,document.getElementById('root')
);

9.4 Key

key는 react가 어떤 항목을 변경, 추가 또는 삭제할지 식별하는 것을 돕는다.

key는 엘리먼트에 안정적인 고유성을 부여하기 위해 배열 내부의 엘리먼트에 지정해야한다.

key를 선택하는 가장 좋은 방법은 리스트의 다른 항목들 사이에서 해당 항목을 고유하게 식별 할 수 있는 문자열을 사용하는 것이다. 대부분의 경우 id를 key로 사용한다.

 

10. form

11, state끌어올리기

12. 합성 vs 상속

13. react로 생각하기

[1]~[6] react 공식 문서

[6.3.1]  https://www.geeksforgeeks.org/

[7.2.2] https://hanjungv.github.io/2018-02-03-1_JS_arrow_function/

  

반응형

댓글