React 공식문서 공부 - 1

heyhey·2023년 1월 11일
0

react

목록 보기
2/17

React 공식문서 공부 - 1

리액트 공식문서를 읽어보며 정리를 해보았다.
공식문서 : https://ko.reactjs.org/docs/hello-world.html
전체를 정리하면서 알아야 할 것 같은 개념들 위주로 정리하였다.

Hello Wolrd


  • ReactDOM.render() 로 부터 React가 시작된다.
  • 첫번쨰는

JSX


const element = <h1>Hello, World</h1>
이 태그는 문자열도 html도 아니다.
JSX 라 부르는 JS를 확장한 문법이며, React element를 생성하기 위해 사용된다.

React는 별도의 파일에 마크업과 로직을 넣어 기술을 분리하는 대신, 둘다 포함하는 컴포넌트로 관심사를 분리한다.
JSX 사용이 필수는 아니지만, JS 코드 안에서 UI 작업을 할때 시각적으로 더 도움이 된다.
React의 경고 메시지를 사용할 수 있다.

표현식 포함

const element = <h1>Hello,{name}</h1>

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

JSX도 표현식이다.

  • 컴파일이 끝나면, JSX 표현식이 정규 JS 함수 호출이 되고 JS 객체로 인식된다.
  • JSX 는 html 보다는 JS에 가깝기 떄문에, camelCase 명명 규칙을 따른다
    • class => className

JSX는 객체를 표현한다.

Babel은 JSX를 React.createElement() 호출로 컴파일한다.

const element = <h1 className="hi">Hello, World</h1>;
const element = React.createElement("h1", { className: "hi" }, "Hello, World");

위의 두 예시는 동일한 코드이다.

React.createElement는 버그가 없는 코드 작성에 도움이 되며, 실행시 다음과 같은 객체를 생성하게 된다.

const element = {
  type: "h1",
  props: {
    className: "hi",
    children: "Hello, Word",
  },
};

이 객체를 React 엘리먼트라고 하며, 화면에서 보고 싶은 것을 나타내는 표현이다.
React는 이 객체를 읽어서, DOM을 구성하고, 최신 상태로 유지한다.

엘리먼트 렌더링


엘리먼트는 React 앱의 가장 작은 단위이다.

엘리먼트는 화면에 표시할 내용을 기술한다.

브라우저의 DOM 엘리먼트와는 달리 React 엘리먼트는 일반 객체 이기 때문에 쉽게 생성할 수 있다.
React DOM은 React 엘리먼트와 일치하도록 DOM을 업데이트한다.

DOM에 엘리먼트 렌더링하기

<div id="root"></div>

root div 태그 안에 들어가는 모든 엘리먼트를 React DOM에서 관리한다.***

  • React로 구현된 애플리케이션은 일반적으로 하나의 루트 DOM 노드가 있다.
  • React를 기존 앱에 통합하려는 경우 원하는 만큼 많은 수의 독립된 루트 DOM 노드가 있을 수 있다.
const root = ReactDOM.createRoot(
  document.getElementById("root") as HTMLElement
);
root.render(<h1>Hello,World<h1/>);

React 엘리먼트를 렌더링하기 위해서는 우선 DOM 엘리먼트ReactDOM.createRoot()에게 전달한 다음,
React 엘리먼트root.render()에게 전달해야한다.

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

React Element는 불변격체이다 ?
엘리먼트는 특정시점의 UI이기 때문에 생성한 이후에는 해달 엘리먼트의 자식이나 속성을 변경할 수 없다.

시계 어플을 만들어 보겠다.

const root = ReactDOM.createRoot(document.getElementById("root"));

function tick() {
  const element = (
    <div>
      <h1>Hello, world!</h1>
      <h2>It is {new Date().toLocaleTimeString()}.</h2>
    </div>
  );
  root.render(element);
}

setInterval(tick, 1000);

1초마다 root.render()를 호출해서, 다시 그리도록 만들었지만, 개발자 도구를 켜서 확인하면, 텍스트만 변경된다
=> 다음장에서..

Component 와 Props


컴포넌트를 통해 UI를 재사용 가능한 개별적인 조각으로 나눠 사용가능하다.
컴포넌트는 JS 함수와 유사하다. props라는 매개변수를 받아서, 화면에 어떻게 표시될는지를 기술하는 React 엘리먼트 반환

함수 컴포넌트

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

클래스형 컴포넌트

class Welcome extends React.Component {
  render() {
    return <h1>Hello, {this.props.name}</h1>;
  }
}

몇가지 규칙을 알아보자

컴포넌트의 이름은 항상 대문자로 시작해야 한다.
props는 읽기 전용이기 때문에 props를 수정해서는 안된다.
이러한 규칙을 위반하지 않기 위해 state라는 정의가 생겨나게 된다.

State


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

클래스형 형태에서 state를 이해해보자

class Clock extends React.Component {
  render() {
    return (
      <div>
        <h1>Hello, world!</h1>
        <h2>It is {this.props.date.toLocaleTimeString()}.</h2>
      </div>
    );
  }
}
  1. 클래스형을 만들었다.
  2. this.props.date.toLocaleTimeString()의 props를 state로 바꿔준다.
  3. 초기 this.state를 지정하는 constructor를 추가한다.
  • 클래스 컴포넌트는 항상 props로 기본 constructor를 호출해야 한다.
class Clock extends React.Component {
  constructor(props) {
    super(props);
    this.state = { date: new Date() };
  }
  render() {
    return (
      <div>
        <h1>Hello, world!</h1>
        <h2>It is {this.props.date.toLocaleTimeString()}.</h2>
      </div>
    );
  }
}
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(<Clock />);

생명주기

componentDidMount()

컴포넌트 출력물이 DOM에 렌더링 된 후에 실행된다.

componentWillUnmount()

생성된 DOM이 삭제될 때마다 실행된다.

아래의 예제는 타이머가 작동하고, 사용되지 않을 때 타이머를 없애는 작업이다

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

  componentDidMount() {
    this.timerID = setInterval(() => this.tick(), 1000);
  }

  componentWillUnmount() {
    clearInterval(this.timerID);
  }

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

const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(<Clock />);

State 실행 순서

  1. <Clock/>root.render()로 전달되었을 떄, React는 <Clock/>constructor()를 호출한다.

  2. <Clock/>은 현재 시각이 포함된 객체로 state를 초기화한다.

  3. React는 <Clock/>render() 메서드를 호출하여 화면에 표시해야할 내용을 알게 된다.

  4. 다음 React는 <Clock/>의 렌더링 출력값을 일치시키기 위해 DOM을 업데이트한다.

  5. <Clock/> 출력값이 DOM에 삽입되면, componentDidMount()를 호출하고, 매초마다 tick() 메소드를 실행하도록 브라우저에 요청

  6. 브라우저가 tick() 메소드를 호출하고, 그 안에서 <Clock/>setState()에 현재 시각을 포함하는 객체를 호출하면서 UI 업데이트 진행

  7. setState() 호출을 통해 React는 state가 변경된 것을 인지하고, 화면에 표시될 내용을 render() 메서드를 통해 다시 호출

  • 이 때, render() 메서드 안의 this.state.date 가 달라지고, 렌더링 출력값은 업데이트된다.
  • React는 이에 따라 DOM을 업데이트 한다.
  1. <Clock/>이 DOM으로 부터 삭제가 된다면 componentWillUnmount() 메서드 호출

setState

State 는 직접 수정하지 않고, setState를 이용한다.

this.state를 지정할 수 있는 유일한 공간은 constructor 이다.

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

this.props와 this.state가 비동기적으로 업데이트가 될 수도 있기 때문에, state를 계산할 때 해당 값에 의존하면 안된다.
기존값에 의존적으로 업데이트를 하고 싶다면 setState 내부에 함수를 넣고 기존 state를 배개변수로 받아와서 사용한다.

this.setState((state, props) => ({
  counter: state.counter + props.increment
}));

State 업데이트는 병합된다.

병합은 얕게 이루어지기 때문에, 변수를 독립적으로 업데이트할 수 있다.

이벤트 핸들링

React 엘리먼트에서 이벤트를 처리하는 방식은 DOM 엘리먼트에서 이벤트를 처리하는 방식과 유사하다.

HTML에서는 문자열을 전달했지만, React에서는 핸들러를 전달한다.
onclick ="function()"
onClick = {function}

  • 주의
    onClick = {this.handleClick}과 같이 () 없이 메서드를 참조할 경우 바인딩이 필요하다.
    콜백에서 this가 동작하기 위해서는 바인딩 작업이 필요하다.

조건부 렌더링

원하는 동작을 캡슐화하는 컴포넌트를 만들 수 있어 상태에 따라 컴포넌트 몇개만 렌더링 가능

컴포넌트 분리하기에 좋다

render() 메서드로 null을 반환하는 것은 생명주기에 영향을 주지 않고, componentDidUpdate는 계속해서 호출이 된다.

profile
주경야독

0개의 댓글