그동안 적지 못했던 리액트 훅에 대해 정리를 해보려 한다.
훅은 함수형 컴포넌트에서 상태 및 다른 React 기능을 더 간결하고 표현적으로 다룰 수 있는 방법을 제공
가장 기본적인 hook, 함수 컴포넌트에서 가변적인 상태를 가지게 해준다.
const [state, setState] = useState(initialState);
원래는 useState 라는 함수가 배열을 반환하고, 이것을 구조 분해 문법으로 꺼내놓은 모습.
// 기존에 우리가 사용하던 방식
setState(number + 1);
// 함수형 업데이트
setState(( )=>{ });
setState의 ( )안에 수정할 값이 아니라, 함수를 넣을 수 있다.
그리고 그 함수의 인자에서는 현재의 state을 가져올 수 있고, { } 안에서는 이 값을 변경하는 코드를 작성할 수 있다.
일반 업데이트 방식은 버튼을 클릭했을 때 배치(batch)로 처리.
우리가 onClick을 했을 때 만약 명령을 세번 내려도, 리액트는 그 명령을 하나로 모아 최종적으로 한번만 실행 시킨다.
(불필요한 리-렌더링을 방지(렌더링 최적화)하기 위해 즉, 리액트의 성능을 위해)
반면에 함수형 업데이트 방식은 3번을 도이에 명령을 내리면, 그 명령을 모아 순차적으로 각각 1번씩 실행 시킨다.
배치(batch)
React에서 배치(batching)는 여러 개의 상태 업데이트를 효율적으로 처리하는 메커니즘.
일반적으로 상태 업데이트 함수(setState 또는 훅의 업데이트 함수)를 호출하면 React는 해당 업데이트를 바로 반영하지 않고 대기열에 추가한다.
그리고 React는 다음 리렌더링 단계에서 대기열에 있는 업데이트들을 일괄적으로 처리한다.
리액트 컴포넌트가 렌더링될 때마다 특정 작업을 수행하도록 설정할 수 있는 Hook.
(렌더링 됐을 때 === 함수 컴포넌트가 실행됐을 때)
"이 배열에 값을 넣으면 그 값이 바뀔 때만 useEffect를 실행할게"
useEffect의 두 번째 인자가 의존성 배열이 들어가는 곳.
useEffect(( )=>{
// 실행하고 싶은 함수
}, [의존성배열])
의존성 배열이 빈 배열인 경우
어떤 함수를 컴포넌트가 렌더링 될 때 단 한번만 실행하고 싶으면 의존성 배열을 [] 빈 상태로 넣으면 된다.
컴포넌트가 사라졌을 때 무언가를 어떻게 실행하는 과정.
useEffect 안에서 return을 해주고 이 부분에 실행되길 원하는 함수를 넣으면 된다.
// src/App.js
import React, { useEffect } from "react";
const App = ( ) => {
useEffect(() => {
// 화면에 컴포넌트가 나타났을 때(mount) 실행하고자 하는 함수를 넣어주세요.
return () => {
// 화면에서 컴포넌트가 사라졌을 때(unmount) 실행하고자 하는 함수를 넣어주세요.
}
}, [])
return <div>hello react!</div>
};
export default App;
DOM 요소에 접근할 수 있도록 하는 React Hook.
function App(){
const ref = useRef("초기값");
console.log("ref 1",ref); //ref 1 ▶ {current: '초기값'}
ref.current = "바꾼 값";
console.log("ref 1", ref); //ref 1 ▶ {current: '바꾼 값'}
return (
}
// ⭐ 이렇게 설정된 ref 값은 컴포넌트가 계속해서 렌더링 되어도 unmount 전까지 값을 유지한다.
useRef 2가지 용도
저장공간
a. state와 비슷한 역할.(state는 변화가 일어나면 다시 렌더링이 일어남. 내부 변수들 초기화)
b. ref에 저장한 값은 렌더링을 일으키지 않음.(ref 값 변화가 일어나도 렌더링으로 인해 내부 변수들이 초기화 되는 것을 막음.)
DOM
prop drilling을 해결하기 위해 등장한 것이 react context API.
전역 데이터를 관리.
// FamilyContext.js
import { createContext } from "react";
export const FamilyContext = createContext(null);
// GrandFather.jsx
import { FamilyContext } from "../context/FamilyContext";
function GrandFather(){
const bean = "완두콩";
const price = "1000원";
return (
<FamilyContext.Provider value={{ bean, price }}>
<Father />
</FamilyContext.Provider>
)
}
export default GrandFather;
// Father.jsx
import Child from "./Child";
function Father() {
return <Child />
}
export default Father;
// Child.jsx
import { FamilyContext } from "../context/FamilyContext";
function Child(){
const data = useContext(FamilyContext);
console.log("data", data); // data ▼Object {bean: "완두콩" price: "1000원" }
}
렌더링 문제
Provider에서 제공한 value가 달라진다면 useContext를 사용하고 있는 모든 컴포넌트가 리렌더링된다. 따라서 value 부분을 항상 신경써줘야한다.
Array.prototype.join([separator])
separator 배열의 각 요소를 구분할 문자열을 지정합니다.
배열의 모든 요소를 연결해 하나의 문자열로 만듭니다.
var a = ['완', '두', '콩'];
console.log(a.join()); // 완,두,콩
console.log(a.join('+')); // 완+두+콩
console.log(a.join('')); // 완두콩