본문 바로가기

③ 프레임워크·라이브러리/react

React 문서 주요개념 요약

728x90

jsx란?

 

react 엘리먼트를 생성하는 javascript를 확장한 문법

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

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

 

바벨이 JSX를 React.createElement() 호출로 컴파일

 

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

 

 

 

엘레멘트 렌더링

 

react element는 react의 가장 작은 구성 요소이며, 브라우저 DOM 과는 다르게 순수 오브젝트이다. 따라서 생성하는 데 비용이 적게 든다.

 

const element = <h1>Hello, world</h1>;
ReactDOM.render(element, document.getElementById('root'));

ReactDOM의 render라는 함수에 두 개의 arguments(React element, Dom element를 전달하면, React element가 Dom element에 소속되고, React element를 html 파서가 DOM element로 인식해 파싱한다. React 엘리먼트는 불변객체 이다. UI를 업데이트 하려면, 다시 새로운 엘레멘트를 생성해야한다. React DOM은 해당 엘리먼트와 그 자식 엘리먼트를 이전의 엘리먼트와 비교하고 DOM을 원하는 상태로 만드는데 필요한 경우에만 DOM을 업데이트합니다.

 

 

 

Component와 Props

 

component는 props(data)를 argument로 받아 element를 리턴하는 function이다.

 

// 함수형 컴포넌트 
function Welcome(props) {
  return <h1>Hello, {props.name}</h1>;
}

// 클래스형 컴포넌트

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

// 사용자 정의 컴포넌트 
const element = <Welcome name="Sara" />;

// 컴포넌트 렌더링
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을 효율적으로 업데이트합니다.

props는 읽기 전용이다. 넘겨 받은 props를 변경해서는 안된다. 함수 컴포넌트나 클래스 컴포넌트 모두 순수 함수이다.

 

 

 

 

state와 class component

 

state는 컴포넌트의 상태이다. state는 props의 값이 변할 때 마다 스스로 컴포넌트가 data를 업데이트 하여 UI로 표시할 수 있게 한다. 

render() 메소드는 state값이 변경될때마다 재실행되는 함수이다. 

class 컴포넌트안에 constructor를 이용해 부모 컴포넌트로부터 props를 전달받는다.

 

 

 

 

lifecycle과 lifecycle method

 

라이프사이클은 컴포넌트가 만들어지고 렌더되고 사라지는 일련의 과정이다.

 

 

 

 

setState와 Top-down data flow

 

state를 수정하기 위해서는 setState를 호출해야 한다. state에 직접 재할당해서는 안된다.

부모컴포넌트는 props를 이용해 자식 컴포넌트에게 data를 물려줄 수 있다. 

 

 

 

 

handling events

 

HTML과 JXS 문법의 차이점

- react에서 event는 camelCase로 이름 짓는다.

- JSX를 사용하면 event handler로 function을 전달한다. (string 아님)

 

// HTML에서 function을 전달할 때
<button onclick="doSomethinig()">
	Do something!
</button>

// JSX에서 function을 전달할 때
<button onClick="{doSomethinig}">
	Do something!
</button>

 

 

 

conditional rendering

 

조건에 맞는 컴포넌트를 렌더링하게 할 수 있다.

 

방법 1.

 

function Greeting(props) {
  const isLoggedIn = props.isLoggedIn;
  if (isLoggedIn) {
    return <UserGreeting />;
  }
  return <GuestGreeting />;
}

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

 

방법 2. 엘레멘트를 변수에 담기

 

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

  handleLogoutClick() {
    this.setState({isLoggedIn: false});
  }

  render() {
    const isLoggedIn = this.state.isLoggedIn;
    let button;
    if (isLoggedIn) {
      button = <LogoutButton onClick={this.handleLogoutClick} />;
    } else {
      button = <LoginButton onClick={this.handleLoginClick} />;
    }

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

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

 

방법3. 논리 && 연산자로 if를 인라인으로 표현하기

 

function Mailbox(props) {
  const unreadMessages = props.unreadMessages;
  return (
    <div>
      <h1>Hello!</h1>
      {unreadMessages.length > 0 &&
        <h2>
          You have {unreadMessages.length} unread messages.
        </h2>
      }
    </div>
  );
}

const messages = ['React', 'Re: React', 'Re:Re: React'];
ReactDOM.render(
  <Mailbox unreadMessages={messages} />,
  document.getElementById('root')
);

 

방법4. 삼항연산자로 if-else 구문 인라인으로 표현하기

 

render() {
  const isLoggedIn = this.state.isLoggedIn;
  return (
    <div>
      {isLoggedIn
        ? <LogoutButton onClick={this.handleLogoutClick} />
        : <LoginButton onClick={this.handleLoginClick} />
      }
    </div>
  );
}

컴포넌트가 렌더링하는 것을 막으려면 null을 반환한다. null을 반환하는 것도 컴포넌트의 라이프 사이클에 영향을 준다. 예를 들어, null을 반환하더라도, 이는 사용자 입장에서 화면이 보이지 않게되는 어떤 이슈가 일어난 것이고, componentDidUpdate가 호출된다.

 

 

 

 

Lists & keys

 

여러개의 컴포넌트를 렌더링하기 위해서는 js의 map을 이용할 수 있습니다.

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

 

const numbers = [1, 2, 3, 4, 5];

function NumberList(props) {
  const numbers = props.numbers;
  const listItems = numbers.map((number) =>
    <ListItem key={number.toString()}
              value={number} />
  );
  return (
    <ul>
      {listItems}
    </ul>
  );
}

 

 

From : Controlled Component

 

html의 form 엘리멘트도 자체적으로 state값을 관리하고, react도 state값을 관리 가능. 이를 단일하게 만들어 두 요소를 결합하여 react에 의해 값이 제어되는 폼 엘리멘트를 '제어 컴포넌트'라고 합니다. 제어 컴포넌트를 사용하면, input의 값은 항상 React state에 의해 결정됩니다.

 

 

State 끌어올리기

- 리액트 안에서 일어나는 데이터에 대해서는 '진리의 원천'을 하나만 두어야 한다. 보통의 경우, state는 렌더링에 그 값을 필요로 하는 컴포넌트에 먼저 추가된다. 그러고 나서 다른 컴포넌트 역시 그 값이 필요하게 되면 그 값을 그들의 가장 가까운 공통 조상으로 끌어올리면 된다.

- 다른 컴포넌트 간에 존재하는 state를 동기화 시키려는 노력 대신 하향식 데이터 흐름에 기대는 것을 추천

- 버그를 찾고 격리하기 쉬워짐

 

render() 메소드는 단순히 UI에 표기할 데이터가 바뀌었다는 것을 리액트가 알아차리도록 합니다. (이때, 실제 돔이 바뀌는 것은 아니다.)정작 다시 렌더링하는 함수는 reactDOM.render() 함수이다. 리액트 돔에서 렌더링 메소드를 실행시키면, 리액트 가상돔이 기존 돔과 같게 렌더링 시킨다. 이때문에? 리액트가 빠른 것이다.

 

 

합성 VS 상속

react는 상속 대신 합성을 사용하여, 컴포넌트 간에 코드를 재사용하는 것이 좋습니다. 

 

// children prop을 이용하여 자식 엘리먼트를 출력에 전달 

function FancyBorder(props) {
  return (
    <div className={'FancyBorder FancyBorder-' + props.color}>
      {props.children}
    </div>
  );
}

function WelcomeDialog() {
  return (
    <FancyBorder color="blue">
      <h1 className="Dialog-title">
        Welcome
      </h1>
      <p className="Dialog-message">
        Thank you for visiting our spacecraft!
      </p>
    </FancyBorder>
  );
}

 

 

React로 사고하기

- component는 오직 한가지 로직만 수행해야 한다. single responsibility principle

- json api와 UI 목업이 있다는 전제하에, 1단계 : UI를 컴포넌트 계층 구조로 나눈다.

- 2단계 : data를 가지고 UI가 렌더링 되게 만든다. 서로 상호작용은 없다.

- 3단계 : state에 할당할 수 있는 핵심 data를 찾는다. props나 다른 state로 부터 얻을 수 없는 고유한 data가 핵심 data.

    1. 부모로부터 props로 전달받은 data인가? No

    2. 시간이 지나도 값이 바뀌지 않는 data인가? No

    3. 다른 data(props, state)로부터 계산을 통해 얻을 수 있는 data인가? No

- 4단계 : state가 위치해야하는 컴포넌트 찾기(공동 계층 구조의 최상위)

- 5단계 : 하위 component 에서 상위 component의 state수정이 가능하게 만들기

 

 

리액트 장점

작게 조각낸 컴포넌트들은 app이 커질 수록 재사용성, 가독성이 높고, 간결해진다.

 

 

참고

 

ko.reactjs.org/docs/hello-world.html

728x90