React 기초 정리

Sungho Cho·2023년 2월 21일
1

react

목록 보기
1/1

React 란?

React는 SPA 개발의 하나로 Facebook에서 개발한 UI 라이브러리로, 복잡한 UI를 간단한 컴포넌트(Component)로 나누어 관리할 수 있도록 도와줍니다. React는 UI의 상태에 따라 뷰를 자동으로 업데이트하고, 재사용성이 높은 컴포넌트를 통해 개발 생산성을 향상시켜주는 등 많은 이점을 제공합니다. 이러한 React를 사용하여 웹 어플리케이션, 서버 사이드 렌더링, 모바일 애플리케이션 등 다양한 분야에서 활용됩니다.

1. SPA 란?

SPA(단일 페이지 애플리케이션) 개발은 전통적인 웹 개발 방식과는 달리, 한 개의 페이지에서 모든 요청에 대한 처리를 하며 필요한 데이터만 비동기적으로 받아와 화면을 갱신하는 방식으로 동작합니다.

SPA에서는 페이지 이동이 없으며, 모든 컨텐츠는 동적으로 로딩됩니다. 이를 위해 대부분의 SPA 프레임워크(예: React, Angular, Vue 등)는 클라이언트 측 라우팅과 데이터 관리를 지원합니다.

SPA는 사용자 경험(UX)을 향상시킬 수 있으며, 속도가 빠르고 반응성이 높아서 모바일 앱과 유사한 경험을 제공할 수 있습니다. SPA 개발 방식은 API 서버와의 연동을 중요하게 다루며, RESTful API를 사용하여 데이터를 주고받습니다.

하지만, SEO(Search Engine Optimization) 문제나 초기 로딩 속도 등의 문제도 있습니다. SPA는 초기 로딩이 느릴 수 있고, JavaScript를 지원하지 않는 일부 검색 엔진에서는 페이지를 인덱싱하기 어려울 수 있습니다. 이러한 문제를 해결하기 위해 서버 사이드 렌더링, 프리렌더링, 라우팅 처리 등의 기술을 적용하여 보완할 수 있습니다.

1-1. 라우팅

라우팅(Routing)은 웹 애플리케이션에서 클라이언트의 요청에 따라 적절한 컨텐츠나 페이지를 반환하는 것을 말합니다. 이를 위해서는 URI(Uniform Resource Identifier)를 기반으로 사용자가 요청한 컨텐츠를 찾아서 반환해야 합니다.

클라이언트 사이드 라우팅은 브라우저에서 처리되며, 페이지 전환 시 전체 페이지를 새로 불러오지 않고, 페이지 내에서 필요한 부분만 동적으로 갱신하는 방식을 말합니다. 이 방식은 페이지 전환의 빠른 응답 속도와 애플리케이션의 부드러운 동작을 보장합니다.

React에서는 react-router-dom 라이브러리를 이용하여 라이팅을 구성합니다.

2. SPA 개발시 사용되는 주요 용어

  1. NPM(Node Package Manager) : 자바스크립트 런타임 환경인 Node.js를 위한 패키지 관리자입니다. NPM은 Node.js를 설치하면 함께 설치되며, 개발자들이 패키지(라이브러리, 모듈 등)를 쉽게 설치하고 관리할 수 있도록 도와줍니다.
  2. yarn : Facebook에서 개발한 JavaScript 패키지 매니저로, npm과 마찬가지로 JavaScript 라이브러리와 프로젝트의 의존성을 관리하는 도구입니다.
  3. 라우팅 (Routing): 다른 주소에 따라 다른 페이지를 보여주는 것을 라우팅이라고 합니다. SPA 개발시 라우팅은 브라우저 히스토리 API나 HTML5 History API를 사용하여 구현됩니다.
  4. 상태 (State): 상태는 컴포넌트에서 사용되는 데이터를 의미합니다. SPA에서는 상태를 관리하기 위해 Redux, MobX, recoil 등의 라이브러리를 사용할 수 있습니다.
  5. 비동기 통신 (Asynchronous communication): SPA에서는 데이터를 서버로부터 비동기적으로 가져옵니다. 이를 위해 AJAX, Fetch API, Axios 등의 라이브러리를 사용할 수 있습니다.
  6. CSR(Client Side Rendering): 서버로부터 초기 HTML, CSS, JavaScript를 받은 후, 웹 브라우저에서 JavaScript를 이용해 렌더링하는 방식입니다. 이는 서버 측에서 모든 로직을 처리하지 않고, 클라이언트 측에서 로직을 처리하는 방식입니다. 대표적으로 React, Vue.js, AngularJS 등의 프레임워크가 CSR을 지원합니다.
  7. SSR(Server Side Rendering): 서버에서 데이터를 받아와서 페이지를 렌더링하여 HTML, CSS, JavaScript를 클라이언트에게 보내주는 방식입니다. 클라이언트 측에서 JavaScript를 이용해 렌더링하지 않고, 서버 측에서 렌더링하는 방식입니다. 대표적으로 Next.js, Nuxt.js 등의 프레임워크가 SSR을 지원합니다.

npm 과 yarn 의 차이

  1. 더 빠른 속도: yarn은 설치 및 업데이트 작업에서 npm보다 더 빠른 속도를 제공합니다.
  2. 보안성: yarn은 모든 패키지를 다운로드하고 설치하기 전에 검증하는 과정을 거치기 때문에 더욱 안전합니다.
  3. 확장성: yarn은 npm과 호환되기 때문에 기존의 npm 패키지를 그대로 사용할 수 있으며, 다양한 확장 기능을 제공하여 기존의 npm보다 더욱 효율적인 개발이 가능합니다.

3. 리엑스 사용되는 주요 용어

  1. JSX:
    JavaScript와 XML을 조합한 문법으로, React에서 UI 컴포넌트를 만들 때 사용됩니다.
  2. Component(컴포넌트):
    UI를 구성하는 독립적인 모듈을 의미합니다. 컴포넌트는 props와 state를 가질 수 있으며, 재사용성이 높습니다.
  3. Prop(프롭):
    부모 컴포넌트에서 자식 컴포넌트로 전달되는 데이터를 의미합니다. Prop은 컴포넌트가 받는 인자로, 변경이 불가능합니다.
  4. State(스테이트):
    컴포넌트 내에서 관리되는 데이터를 의미합니다. State는 컴포넌트 내부에서 변경 가능합니다.
  5. Event(이벤트):
    사용자의 동작(클릭, 입력 등)을 처리하기 위한 함수를 의미합니다. React에서는 이벤트를 처리하기 위해 SyntheticEvent 객체를 사용합니다.
  6. Props drilling(프롭스 드릴링):
    상위 컴포넌트에서 하위 컴포넌트로 데이터를 전달하기 위해 여러 단계를 거쳐 전달하는 것을 의미합니다.
  7. State lifting(스테이트 리프팅):
    하위 컴포넌트에서 상위 컴포넌트로 데이터를 전달하기 위해 상위 컴포넌트에서 콜백 함수를 통해 데이터를 변경하는 것을 의미합니다.
  8. Conditional rendering(조건부 렌더링):
    조건에 따라 다른 컴포넌트를 렌더링하는 것을 의미합니다. 이를 위해 삼항 연산자나 && 연산자를 사용합니다.
  9. Lifecycle(라이프사이클):
    컴포넌트가 생성되고 소멸될 때 일어나는 일련의 이벤트를 의미합니다. 라이프사이클 메소드를 사용하여 컴포넌트의 행동을 제어할 수 있습니다.
  10. Hook(훅):
    React 16.8 버전 이후 추가된 기능으로, 함수형 컴포넌트에서 상태 관리나 라이프사이클 이벤트 등을 처리하기 위한 함수입니다.

4. 컨벤션

React 코딩 컨벤션은 코드를 작성하는 방법을 표준화하여 가독성을 향상시키고 유지보수를 용이하게 합니다.

  1. 파일명은 PascalCase로 작성합니다.
예:App.js, MyComponent.jsx
  1. 컴포넌트 이름은 CamelCase로 작성합니다.
예: function myFunctionComponent() {}
  1. 각 컴포넌트는 한 파일에 작성합니다.
  2. props는 CamelCase로 작성합니다.
예: <MyComponent myProp="value" />
  1. 컴포넌트 내부에서 props를 변경하지 않습니다.
  2. setState() 메소드를 사용하여 컴포넌트의 상태를 변경합니다.
  3. 함수의 이름은 동사로 시작하여 해당 함수가 어떤 작업을 수행하는지 명확하게 나타냅니다.
  4. 컴포넌트의 라이프사이클 메소드는 해당 순서대로 정렬합니다.
  5. 컴포넌트 내부에서 로직과 뷰를 분리하며, 각각의 역할이 명확하도록 작성합니다.
  6. CSS 클래스 이름은 kebab-case로 작성합니다.
예: <div className="my-class" />
  1. 조건부 렌더링을 위해서 삼항 연산자보다는 && 연산자를 사용합니다.
예: 
{isLoggedIn ? <UserProfile /> : ''} X
{isLoggedIn && <UserProfile />} O
  1. 컴포넌트의 props와 state가 변경될 때, 해당 컴포넌트만 다시 렌더링하도록 작성합니다.
  2. 코드를 작성하기 전에 eslint와 같은 코드 검사 도구를 사용하여 코드를 자동으로 검사하도록 설정합니다.
  3. URL작성시 URL은 kebab-case로 작성합니다.
예: /my-account/my-profile
  1. 들여쓰기: 4칸을 사용합니다.
  2. 세미콜론(;) 사용: 문장 끝에 항상 세미콜론을 사용합니다.
  3. 상수: 대문자와 언더스코어를 사용하여 작성합니다.

5. React CRA로 프로젝트 생성

React CRA(Create React App)란, React 앱 개발을 위한 보일러플레이트(프로젝트 템플릿)로, React 프로젝트를 쉽게 시작할 수 있도록 해주는 공식 도구입니다.

React CRA를 사용하면, 프로젝트를 생성하고 개발 서버를 실행하는 것이 쉽고 빠르며, 초기 설정과 구성이 자동으로 이루어지므로 개발자는 바로 애플리케이션의 로직 구현에 집중할 수 있습니다.

React CRA로 시작하는 방법은 다음과 같습니다.

  1. Node.js 설치 확인
    React CRA는 Node.js 버전 10 이상을 필요로 합니다.
    따라서, 먼저 Node.js를 설치하고 버전을 확인해야 합니다.
    Node.js 버전이 작업자들과 맞지 않다면 버전을 맞도록 해야 하며 기본적으로 Node 설치는 하나의 버전만 설치 가능하므로 NVM(Node Version Manager)을 설치하여 Node 버전을 관리 합니다.

    NVM 설치는 window 와 MAC 이 다르므로 설치시 유의해서 설치 합니다.

  2. React CRA 프로젝트 생성
npx react-create-app [프로젝트 이름]

5-1. React CRA 생성시 폴더 구조

my-app/          
  README.md       // 프로젝트에 대한 설명을 담은 파일입니다.
  node_modules/   // 프로젝트에서 사용하는 모든 라이브러리와 도구들이 설치되는 폴더입니다.
  package.json    // 프로젝트의 메타데이터와 의존성 정보를 담고 있는 파일입니다.
  public/         // 정적 파일들이 위치하는 폴더입니다. 
    index.html    // 프로젝트의 진입점 HTML 파일입니다.
    favicon.ico   
  src/            // 프로젝트의 모든 소스 코드가 위치하는 폴더입니다.
    App.css
    App.js        // create-react-app 명령어로 생성된 기본 앱 컴포넌트입니다.
    index.css
    index.js      // React 앱의 진입점 JavaScript 파일입니다.
    logo.svg
  .gitignore

6. prettier && eslint

6-1. prettier

Prettier는 코드 포맷팅 툴 중의 하나로, 코드의 가독성을 높이고 일관성 있는 스타일로 코드를 작성할 수 있도록 도와줍니다.
1. prettier 설치하기

npm install --save-dev prettier
  1. .prettierrc 파일 생성하기
    Prettier를 설정하기 위해 프로젝트 루트 디렉토리에 .prettierrc 파일을 생성합니다. 이 파일에서는 Prettier가 적용될 코드 스타일을 설정할 수 있습니다.
module.exports = {
	singleQuote: true,
    // 문자열은 작은 따옴표로 통일
    semi: true,
    //코드 마지막에 세미콜른이 자동 생성
    tabWidth: 4,
    // 들여쓰기 너비는 4칸
    trailingComma: 'all',
    // 객체나 배열 키:값 뒤에 콤마 생성
    printWidth: 160,
    // 코드 한줄이 maximum 80칸
    arrowParens: 'avoid',
	// 화살표 함수가 하나의 매개변수를 받을 때 괄호 생략
};

추가설명 Prettier Options

  1. .prettierignore 파일 생성하기 (옵션)
    Prettier를 사용할 때 무시해야 할 파일이 있다면 .prettierignore 파일을 생성하고 해당 파일 목록을 작성합니다.

  2. package.json 파일 수정하기
    package.json 파일의 scripts 항목에 Prettier를 실행하는 스크립트를 추가합니다.

"scripts": {
  "format": "prettier --write \"src/**/*.js\""
},

6-2. esLint

ESLint는 ES(Ecma Script)
[Lint](https://ko.wikipedia.org/wiki/%EB%A6%B0%ED%8A%B8_(%EC%86%8C%ED%94%84%ED%8A%B8%EC%9B%A8%EC%96%B4) (소스 코드를 분석하여 프로그램 오류, 버그, 스타일 오류, 의심스러운 구조체에 표시를 달아놓기 위한 도구) 자바스크립트 코드에서 일관성을 유지하고 잠재적인 오류를 발견하기 위한 정적 분석 도구 중 하나입니다. React 프로젝트에서 ESLint를 적용하기 위해서는 다음과 같은 단계를 따르면 됩니다.

  1. ESLint 설치
npm install --save-dev eslint
  1. ESLint 설정 파일 생성하기
    ESLint를 설정하기 위해 프로젝트 루트 디렉토리에 .eslintrc.json 파일을 생성합니다. 이 파일에서는 ESLint가 적용될 규칙을 설정할 수 있습니다.
{
  "env": {
    "browser": true,
    "es6": true
  },
  "extends": [
    "plugin:react/recommended",
    "airbnb",
    "prettier",
    "prettier/react"
  ],
  "globals": {
    "Atomics": "readonly",
    "SharedArrayBuffer": "readonly"
  },
  "parserOptions": {
    "ecmaFeatures": {
      "jsx": true
    },
    "ecmaVersion": 2018,
    "sourceType": "module"
  },
  "plugins": ["react", "prettier"],
  "rules": {
    "react/prop-types": "off",
    "prettier/prettier": "error"
  }
}

위의 설정 코드에서는 다음과 같은 내용이 포함되어 있습니다:

  • env: ESLint가 JavaScript 실행 환경을 인식할 수 있도록 설정합니다. 이 경우, 브라우저와 ECMAScript 6 (ES6)를 지원하는 환경으로 설정합니다.
  • extends: ESLint가 사용할 규칙을 설정합니다. plugin:react/recommended, airbnb, prettier, prettier/react 플러그인과 규칙을 함께 사용합니다.
  • globals: 프로젝트 전역에서 사용되는 전역 변수를 설정합니다.
  • parserOptions: ESLint가 사용할 파서 옵션을 설정합니다. 이 경우, JSX 문법을 인식할 수 있도록 설정합니다.
  • plugins: ESLint가 사용할 플러그인을 설정합니다. 이 경우, react와 prettier 플러그인을 사용합니다.
  • rules: ESLint가 적용할 규칙을 설정합니다. 이 경우, react/prop-types 규칙을 해제하고, prettier/prettier 규칙을 에러로 설정합니다.

위의 코드에서는 AirBnb의 JavaScript 스타일 가이드를 기반으로 하고 있습니다. 이 가이드를 따르는 것이 좋은 코드 스타일을 유지하기 위한 방법 중 하나입니다.

7. React 라이프 사이클

React에서 라이프사이클(lifecycle)이란 컴포넌트가 마운트, 언마운트, 업데이트되는 과정에서 호출되는 여러 메서드를 말합니다.

  1. 마운트(Mount):
  • constructor()
  • getDerivedStateFromProps()
  • render()
  • componentDidMount()
  1. 업데이트(Update):
  • getDerivedStateFromProps()
  • shouldComponentUpdate()
  • render()
  • getSnapshotBeforeUpdate()
  • componentDidUpdate()
  1. 언마운트(Unmount):
  • componentWillUnmount()

7-1. function Component

React 16.8 버전 이후부터는 함수형 컴포넌트에서도 Hook을 사용하여 라이프사이클 메서드와 비슷한 작업을 수행할 수 있습니다. 아래는 함수형 컴포넌트에서 useEffect Hook을 사용하여 라이프사이클 메서드와 비슷한 작업을 수행하는 예제 코드입니다.

import React, { useState, useEffect } from 'react';

function MyComponent(props) {
  const [count, setCount] = useState(0);

  // componentDidMount와 componentDidUpdate 역할
  useEffect(() => {
    console.log('Component did mount or update');
    // 어떤 작업을 수행하고 싶다면 이곳에서 처리합니다.
    // 주의할 점은 무한루프에 빠지지 않도록 의존성 배열을 설정해야합니다.
  }, [count]);

  // componentWillUnmount 역할
  useEffect(() => {
    return () => {
      console.log('Component will unmount');
      // 어떤 작업을 수행하고 싶다면 이곳에서 처리합니다.
    }
  }, []);

  const handleClick = () => {
    setCount(count + 1);
  };

  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={handleClick}>Increase count</button>
    </div>
  );
}

export default MyComponent;

8. React Hooks

Hook은 React 버전 16.8부터 React 요소로 새로 추가되었습니다.
Hook을 이용하여 기존 Class 바탕의 코드를 작성할 필요 없이 function 형태로 상태 값과 여러 React의 기능을 사용할 수 있습니다.

Hook은 조건문, return문 에 상용할 수 없으며 React Component 내의 전역으로서만 사용가능하다.

8-1. useState

컴포넌트의 state(상태)를 관리 할 수 있다.

상태에 따라, 다른 화면 출력

import { useState } from "react";
const App = () => {
  const [isMobile, setIsMobile] = useState(false);
  console.log(isMobile) // false
  setIsMobile(true);
  console.log(isMobile) // true
  return '';
}

8-2. useEffect

렌더링 이후에 실행할 코드를 만들수 있다.

어떤 변수가 변경될때마다(의존성), 특정기능이 작동하도록 할 수 있다.

  • 비동기 방식
import { useEffect } from 'react'
const App = (data) => {
  useEffect(() => {
    console.log('data Change'); // data 가 변경될 때 마다 해당 console.log 출력
    return () => {
      console.log('언마운트') // 컴포넌트 초기화에 사용 
    }
  }, [data])
  return '';
}

8-3. useLayoutEffect

모든 DOM 변경 후 브라우저가 화면을 그리기(render)전에 실행되는 기능을 정할 수 있다.

  • 동기 방식 ( 끝날때까지 React가 기다림 )
import { useLayoutEffect } from 'react'
const App = (data) => {
  useLayoutEffect(() => {
    console.log('data Change'); // data 가 변경될 때 마다 해당 console.log 출력
    return () => {
      console.log('Layout이 사라짐') // 컴포넌트 초기화에 사용 
    }
  }, [data])
  return '';
}

8-4. useContext

부모컴포넌트와 자식컴포넌트 간의 변수와 함수를 전역적으로 정의할 수 있다.

// newContext.js
import { createContext } from "react"  // createContext 함수 불러오기
// context안에 homeText란 변수를 만들고, 공백("") 문자를 저장한다.
const newContext = createContext({
  homeText: "",
})
import React from "react";
import Home from "./Home"; // 자식 컴포넌트 불러오기
import { newContext } from "./newContext"; // context 불러오기
const App = () => {
  // context에 저장할 정보를 입력한다.
  const homeText = "is Worked!"
  // NewContext.Provider로 우리가 만든 context를 사용할 부분을 감싸준다.
  return (
    <newContext.Provider value={{ homeText }}>
      <Home />
    </newContext.Provider>
  );
}
export default App;
// Home.js
import React from "react";
import { useContext } from "react";
import { newContext } from "../newContext";
const Home = () => {
  // useContext hook 사용해서, newContext에 저장된 정보 가져오기
  const { homeText } = useContext(newContext);
  // 불러온 정보 사용하기!!
  return (  
    <p>{homeText}<p>
  );
}
export default Home;

React에서 context 없이 변수나 함수를 자식 컴포넌트로 전달하려면 Prop을 이용한 부모자식에서만
가능하므로 자식이 자식컴포넌트가 계속 추가 될수록 계속 prop을 넘겨야 하는데
context 를 이용하면 중간을 처지지 않고 바로 제일 하위 자식으로 전달할 수 있다.

전달하고자하는 컴포넌트에 context를 만들면, 불필요한 호출이 추가될 수 있으므로, context 전용 파일을 만들어야 한다.
[예시 조건]

컴포넌트 : A, B, C, D ( A가 최상위 컴포넌트 )

전달 : A -> D

A 컴포넌트에 context 생성

D 컴포넌트에서 context 불러옴


[실행 과정]

A가 렌더링되며, B, C, D를 차례로 불러옴

D에서 context를 가져오기위해 A를 다시불러옴

A를 다시 불러오면서, 불필요한 중복이 발생함

8-5. useMemo

의존성 배열에 적힌 값이 변할 때만 값,함수를 다시 정의할 수 있다. ( 재랜더링시 정의 안함 )

Memoization : 과거에 계산한 값을 반복해서 사용할때, 그 값을 캐시에 저장하는 것

  • 재귀함수에 사용하면, 불필요한 반복 수행을 대폭 줄일 수 있다.
  • 의존성을 가지므로, 첫렌더링시에만 저장할 변수를 설정할 수 있다.
import { useMemo } from 'react'
const App = () => {
  const data = useMemo(() => "data", []);
  // 데이터 변수는 의존성 배열(dependency) []에따라 선언된다. ( []사용시, 첫 렌더링 시에 1번만 선언 )
  return '';
}

8-6. useCallback

의존성 배열에 적힌 값이 변할 때만 값,함수를 다시 정의할 수 있다. ( 재랜더링시 정의 안함 )

useMemo의 함수버전

import { useCallback } from 'react'
const App = () => {
  const data = useCallback(() => console.log(data), []);
  // 데이터 변수는 의존성 배열(dependency) []에따라 선언된다. ( []사용시, 첫 렌더링 시에 1번만 선언 )
  return '';
}

8-7. useRef

HTML요소(태그)나 컴포넌트의 메모리주소를 가져와, 객체(레퍼런스) 형식으로 관리할 수 있다.

  • current 속성을 가지고 있는 객체를 반환한다.
  • current 값이 바뀌어도, 재렌더링 되지 않는다.
  • 재렌더링시에도, current 값은 없어지지 않는다.
import React, { useRef } from "react";
const Field = () => {
  const inputRef = useRef(null);
  function handleFocus() {
    inputRef.current.focus();
  }
  return (
    <>
      <input type="text" ref={inputRef} />
      <button onClick={handleFocus}>입력란 포커스</button>
    </>
  );
}

8-7-1. forwardRef

useRef로 만든 래퍼런스를 상위 컴포넌트로 전달할 수 있다.

import React, { useRef, forwardRef } from "react";
const Input = forwardRef((props, ref) => {
  return <input type="text" ref={ref} />;
});
function Field() {
  const inputRef = useRef(null);
  function handleFocus() {
    inputRef.current.focus();
  }
  return (
    <>
      <Input ref={inputRef} />
      <button onClick={handleFocus}>입력란 포커스</button>
    </>
  );
}

forwardRef() 함수를 호출할 때 다음과 같이 익명 함수를 넘기면 브라우저에서 React 개발자 도구를 사용할 때 컴포넌트의 이름이 나오지 않아서 불편할 수가 있는데요.

React 개발자 도구에서 forwardRef() 함수를 사용해도 컴포넌트 이름이 나오게 하는 3가지 방법.

  1. forwardRef() 함수에 익명 함수를 대신에 이름이 있는 함수를 넘깁니다.
const Input = forwardRef(function Input(props, ref) {
  return <input type="text" ref={ref} />;
});
  1. forwardRef() 함수의 호출 결과로 기존 컴포넌트를 대체합니다.
function Input(props, ref) {
  return <input type="text" ref={ref} />;
}
Input = forwardRef(Input);
  1. forwardRef() 함수의 호출 결과의 displayName 속성에 컴포넌트 이름을 설정해줍니다.
const Input = forwardRef((props, ref) => {
  return <input type="text" ref={ref} />;
});
Input.displayName = "Input";

8-8. useImperativeHandle

useRef로 만든 래퍼런스의 상태에 따라, 실행할 함수를 정의 할 수 있다.

import {useRef, useImperativeHandle} from 'react'
const ImperativeTextInput = (props, ref) => {
  const textInputRef = useRef<TextInput | null>(null);
  
  // ref을 전달받아, 메소드를 만들어준다. ( 다른 ref 호출 가능 )
  useImperativeHandle(
    ref,
    () => ({
      focus() {
        textInputRef.current?.focus();
      },
      dismiss() {
        Keyboard.dismiss();
      },
    }),
    [],
  );
  return <TextInput ref={textInputRef} {...props} />;
};

export default forwardRef(ImperativeTextInput);

8-9. useReducer

state(상태) 업데이트 로직을, reducer 함수에 따로 분리 할 수 있다.

import React, { useReducer } from "react";

function init(initialState) {
  return { count: initialState };
}

function reducer(state, action) {
  switch (action.type) {
    case "INCREMENT":
      return { count: state.count + action.payload };
    case "DECREMENT":
      return { count: state.count - action.payload };
    case "RESET":
      return init(action.payload);
    default:
      throw new Error("unsupported action type: ", action.type);
  }
}

const Counter = ({ initialCount }) => {
  const [state, dispatch] = useReducer(reducer, initialCount, init);

  return (
    <>
      <h2>{state.count}</h2>
      <button onClick={() => dispatch({ type: "RESET", payload: 0 })}>
        초기화
      </button>
      <button onClick={() => dispatch({ type: "INCREMENT", payload: 1 })}>
        증가
      </button>
      <button onClick={() => dispatch({ type: "DECREMENT", payload: 1 })}>
        감소
      </button>
      <button onClick={() => dispatch({ type: "kkkkkkkkk", payload: 1 })}>
        에러
      </button>
    </>
  );
};

export default Counter;

8-10. useDebugValue

사용자 정의한 Hook의 디버깅을 돕기 위해 쓰이며 chrome React Developer Tools 을 통해 사용한 hook 의 데이터 값이나 혹은 label 식으로 입력하여 어떤 Hook 을 썻는지 알 수 있다.

import { useDebugValue, useState } from 'react'
export const useUserInformation = (user) => {
  const [user, setUser] = useState(user);
  useDebugValue(`useUserInformation Hook ${user}`);
  return user;
}
profile
Front 개발합시다.

0개의 댓글