React16

React16

React 16

  • React 16에 추가된 기능이 나왔는데 사람들이 많이 사용하지 않음. 좋은 기능이 있는데…

Return Types Strings and Fragments

  • 이전 component는 null인게 규칙이었다.
  • component 아니면 null이어서 string같은 type을 return할 수 없었다.
  • return할 때, 하나가 아닌 두 개를 리턴하고 싶을 때도 있다.
// 예전 react에서는 하나의 element로 묶어야 했다.(react가 여러 개를 한 번에 return하지 못하니까)
class  ReturnTypes  extends  Component {
 render() {
  return (
   <header></header>
   <div></div>
   <footer></footer>
  );
 }
}
 
// 이렇게 사용하고 싶다면 예전에는 array(key를 넘겨줒교)나 span을 이용했다.
return (
 [<header  key={1}></header>,
 <div  key={2}></div>,
 <footer  key={3}></footer>]
);

또는

// 거의 대부분의 리액트 프로젝트가 이렇게 되어있지만, 그룹핑을 해야 하기 때문에 별로다...
return (
 <span>
  <header  />,
  <div  />,
  <footer  />,
 </span>
);

// 불필요한 코드가 많다.
// span을 사용하면 html코드에 span이 잡히고, css도 꼬일 수 있다.
React 16에서는 fragments라는 걸 활용할 수 있다.

import  React, { Component, Fragment } from  'react';

class  ReturnTypes  extends  Component {
render() {
 return (
  <Fragment>
   <header  />,
   <div  />,
   <footer  />
  </Fragment>
 );
}

또는

return (
// Fragment 생략 가능(create-react-app은 아직 지원하지 않음, webpack은 정상 작동)
 <>
  <header  />
  <div  />
  <footer  />
 </>
);
return string도 가능하다.
// App.js
import  React, { Component, Fragment } from  'react';

class  ReturnTypes  extends  Component {
 render() {
  return  'Hello';
 }
}

class  App  extends  Component {
 render() {
  return (
   <Fragment>
    <ReturnTypes  />
   </Fragment>
  );
 }
}

export  default  App;

// 화면에 Hello가 출력됨

Portals

  • react.js는 div를 찾아서 mount하는데… index.js에 있는 root id를 mount한다. 그런데, 가끔은 리액트 루트 밖에서 터치하고 싶은 경우가 있다.(css의 색상 테마 등등…)
  • Portals를 사용하면 리액트 루트 밖에 리액트를 넣을 수 있게 해준다.
  • 다른 페이지에서 로딩할 때 우용(iframe이거나 혹은 html을 변경하지 못할 때, 워드프레스 작업을 할 때, 리액트 플러그인을 만들 때 등등…)
<!-- index.html -->
<body>
 <noscript>
  You need to enable Javascript to run this app.
 </noscript>
 <!-- react scope 밖에 위치해 있다.(정적인 html) -->

 <header> // this
  <h1>Can't touch this</h1>
 </header>
 <div  id="root"></div>
</body>
portals 사용 예는 다음과 같다.
<!-- index.html -->
<body>
 <noscript>
  You need to enable Javascript to run this app.
 </noscript>
 <header>
  <h1>Can't touch this</h1>
  <span  id='touchme'></span>
 </header>
 <div  id="root"></div>
</body>
// App.js
import { createPortal } from  'react-dom';

class  Portals  extends  Component {
 // render를 통해 element가 아닌 Portal(react dom안에 위치해 있음)을 return
 render() {
  return  createPortal(
   <Message  />,
   // Portal에게 어디에 마운트해야 할지 알려줘야 한다.
   document.getElementById('touchme');
  );
 }
}

const  Message = () =>  "Just touch it!";

class  App  extends  Component {
 render() {
  return (
   <Portals  />
  );
 }
}

export  default  App;

Error Boundaries

  • 컴포넌트가 자식 컨포넌트의 에러를 관리할 수 있게 해준다.
  • 자식 컴포넌트에 대한 에러에게만 한정되는 기능이다.
  • 에러를 구분하고, 에러에 대응할 수 있다.
// 보편적인 에러를 만들어보겠다.
class  ErrorMaker  extneds  Component {
 state = {
  friends: ["test", "one", "two", "three"];
 };

 componentDidMount = () => {
  setTimeout(() => {
   this.setState({ friends:  undefined });
  }, 2000);
 };

 render() {
  const { friends } = this.state;
  return  friends.map(friend  =>  ` ${friend} `); // error
 }
}

const  ErrorFallback = () =>  "Sorry something want wrong";

class  App  extends  Component {
 state = { hasError:  false }

 ComponentDidCatch = (error, info) => {
  console.log(`catched ${error} the info i have is ${JSON.stringify(info)}`);
 this.setState({ hasError:  true });
 }

 render() {
  const { hasError } = this.state;
  return (
   {hasError ? <ErrorFallback /> : <ErrorMaker />}
  )
 }
}
컴포넌트마다 if/else 구분이 있도록 개발하면 안된다. 이 문제는 HOC로 해결한다.

Error Boundaries with Higher Order Components(HOC)

  • 에러 관리법
const  BoundaryHOC = ProtectedComponent  =>  class  BoundaryHOC  extends  Component {
 state = { hasError:  false };
 
 componentDidCatch = () => {
  this.setState({ hasError:  true });
 }

 render() {
  const { hasError } = this.state;
  if (hasError) {
   return  <ErrorFallback  />
  } else {
   return  <ProtectedComponent  />
  }
 }
}

export  default  BondaryHOC(App); // 우리가 만들 BoundaryHOC로 컴포넌트 보호

this.setState(null)

  • 상태를 null로 바꾸는 것
  • 리액트 development process에서 컴포넌트를 업데이트하고 싶지 않을 때 사용
// 피자가 20까지만 상태 변경이 되도록 하는 예제(return null 활용)

import  React, { Component } from  'react';

const  MAX_PIZZAS = 20;

const  eatPizzas = (state, props) => {
 const { pizzas } = state;

 if (pizzas < MAX_PIZZAS) {
  return {
   pizzas = pizzas + 1
  }
 } else {
  return  null;
 }
}

class  Controlled  extends  Component {
 state = { pizzas: 10 };

 render() {
  const { pizzas } = this.state;

  return (

   <Button  onClick={this._handleClick}>{`I habe eaten ${pizzas}  ${pizzas === 1 ? "pizza" : "pizzas"  }`}</Button>
  );
 }

 _handleClick = () => {
  this.setState(eatPizzas);
 }
}

참고

master-react16

댓글

가장 많이 본 글