개발공부일지
React - children props, hooks 본문
목차
1. children props
2. Hooks
① useRef
② useMemo
③ useContext
④ useCallback
⑤ useReducer
⑥ custom hook : useInput
1. children props
- 주로 컴포넌트 간의 데이터 전달이나 구조를 유연하게 관리하기 위해 사용 (어떤 내용이든 전달할수있음!)
- 부모 컴포넌트는 자식 컴포넌트에게 데이터, 함수 또는 JSX 요소와 같은 내용을 전달할 수 있음
- 코드의 재사용성을 높이고 컴포넌트 간의 결합도를 낮출 수 있다고한다!
export const LoginButton = ({ children }) => {
return <button>{children}</button>;
};
2. Hooks
① useRef
https://react.dev/reference/react/useRef#usage
- react내에서 querySelector를 사용하지않고 태그를 선택해야할 때 사용함!
- ref에 속성에 전달하면 화면 그리고 인스턴스 객체의 속성에 태그가 요소로 참조된다.
- useRef의 인스턴스를 전달한 해당 요소가 전달
- current 키에 값으로 보여준다!
import { useRef } from "react";
const ref = useRef(initialValue)
② useMemo
https://react.dev/reference/react/useMemo
- useMemo는 메모이제이션, 컴포넌트의 성능을 최적화 시키기위해 사용하는 hook
- 동일한 연산을 반복해야하는 경우, 이전에 연산한 값을 메모리에 저장해두고 꺼내쓰는!
- 성능 최적화를 위해 메모이제이션된 값을 반환하는 데에 사용한다!
- 계산 비용이 높은 연산의 결과를 캐시하여, 해당 값이 변경되지 않는 한 매번 다시 계산하는 것을 방지한다.
- 부모 컴포넌트가 리랜더링되면 자식모두가 리랜더링 되어버리는데
- 다시 리랜더링 되었을때 불필요한 연산이 일어날수도있기 때문에 자식컴포넌트 보호해준다.
- 예를들어 게시판에 아이템이 100개의 component일때
- 100개 다 리랜더링된다면 과부하걸리는데
- useMemo를 사용해서 바뀐내용이 없다면 다시 그리지않게하는것!
- 메모이제이션 기법 : 컴퓨터 프로그램이 동일한 계산을 반복
- 이전값을 메모리에 저장해놓고 동일한 연산 반복 수행 제거 목적
import { useState, useMemo } from "react";
export const Memo = () => {
const [immutableNum, setImmutableNum] = useState(0);
const [count, setCount] = useState(0);
const increment = () => {
console.log("증가");
setCount(count + 10);
if (count == 50) setImmutableNum(1 + count);
};
const tempValue = useMemo(() => {
console.log("메모 hook 실행");
return immutableNum + 2;
}, [immutableNum]);
// Memo에서 새로운 연산을 처리할지 말지 immutableNum 을 주시함 useEffect처럼
console.log(`실행`);
return useMemo(() => {
console.log(`자식 컴포넌트`);
return (
<div>
<p>count : {count}</p>
<button onClick={increment}>+</button>
<p>tempValue : {tempValue}</p>
</div>
);
}, [immutableNum, count]);
};
③ useContext
https://react.dev/reference/react/useContext
- context를 사용하면 props를 전달하지 않아도 된다고 공식문서
- 전역상태 변수를 사용
- 참조를 부모에서 주입시켜준 자식은 어디서든 접근가능함!
- context는 객체로 createContext로 context로 객체를 만들고
- Provider : context객체 하위 자식에게 값을 전달해줌
import { createContext, useState } from "react";
import A from "./A";
export const Global = createContext();
export const Context = () => {
const [login, setLogin] = useState(false);
const obj = {
login,
setLogin,
};
return (
<>
<Global.Provider value={obj}>
<A />
</Global.Provider>
</>
);
};
import React, { useContext } from "react";
import { Global } from "./Context";
const A = () => {
const { login, setLogin } = useContext(Global);
return (
<>
<div>{login ? "로그인 상태" : "로그인안됨"}</div>
<button
onClick={() => {
setLogin(!login);
}}
>
로그인 or 로그아웃
</button>
</>
);
};
export default A;
④ useCallback
https://react.dev/reference/react/useCallback
- useCallback
- 첫번째 인자 : 콜백함수
- 두번째 인자 : 배열
- 첫번째의 인자로 전달한 함수를 두번째 인자 주시하고 있는 값이 변경될때 까지 연산하지않음
- component안에 리랜더링이 될때 새로운 함수가 생성되지않음!
- 주시하는 값이 바뀌면 그때 함수 생성해서 연산함!
- 주시하고 있는 값이 바뀌지 않는 이상 이전 함수의 기존 메모리의 데이터로 연산을 하지않고 결과를 반환함
- memo쓰면 memo의 스코프만 메모이제이션이 되고 useCallback을 사용해서 함수 최적화하기
- 예를들어, 무한 스크롤하는데 10개만 보여줘야하고, 랜더링이 되었을때 이전값 연산없이 그대로 보여줘야할때
- 함수의 내용이 메모이제이션이 되는것
- 20개로 변환되면 함수의 연산을 다시 정의
import { useCallback, useState } from "react";
export const Callback = () => {
const [hi, setHi] = useState(0);
const [bye, setBye] = useState(0);
const hiClickHandler = useCallback(() => {
setHi(hi + 1);
}, [bye]);
const byeClickHander = useCallback(() => {
setBye(bye + 1);
}, [bye]);
return (
<>
<div>
<div>
<span>{hi}</span>
<button onClick={hiClickHandler}>hi</button>
</div>
<div>
<span>{bye}</span>
<button onClick={byeClickHander}>bye</button>
</div>
</div>
</>
);
};
⑤ useReducer
https://react.dev/reference/react/useReducer
- useState를 대체할수있는 hook함수
- 여러개의 상태를 구분지어 사용할수있음 (가독성, 비동기처리)
- state : 사용할 상태
- dispatch : reducer라는 함수(메뉴판) 실행
- 전달한 문자열을 보고 (어떤함수 실행할건지)
- 현재 state와 action 객체를 받아서
- action에는 객체로 매개변수가 전달
- 상태를 업데이트 할때 실행함
- initialState : 초기값 전달(object 객체)
- reducer : 이전 상태와 action 객체의 내용을 합쳐서 { ...state, { id : action.payload.id }} 이런식으로 사용 상태관리 해줌
- useState보다 복잡한 프로세스를 가독성 좋게 처리가 가능함!
- dispatch → action → reducer 순으로 state변경!!!!!!
import { useReducer } from "react";
export const Reducer = () => {
const initialState = {
count: 0,
};
// ENUM
const INCREMENT = "INCREMENT";
const DECREMENT = "DECREMENT";
const reducer = (state, action) => {
const { type, payload } = action;
switch (type) {
case INCREMENT:
return { ...state, count: state.count + payload.count };
case DECREMENT:
return { ...state, count: state.count - payload.count };
default:
// state는 꼭 반환해주어야함!
return state;
}
};
const [state, dispatch] = useReducer(reducer, initialState);
return (
<>
<p>{state.count}</p>
<button
onClick={() =>
dispatch({ type: INCREMENT, payload: { count: 1 } })
}
>
+
</button>
<button
onClick={() =>
dispatch({ type: DECREMENT, payload: { count: 1 } })
}
>
-
</button>
</>
);
};
⑥ custom hook : useInput
import { useState } from "react";
const useInput = (initialValue) => {
const [value, setValue] = useState(initialValue);
const onChange = (e) => {
console.log(e.target.value);
setValue(e.target.value);
};
return { value, onChange };
};
export default useInput;
- value, onChange를 내보낸이유는 input의 속성으로 바로 주입가능하기때문에!
import { LoginLabel } from "../atoms/LoginLabel";
import { LoginInput } from "../atoms/LoginInput";
import { LoginButton } from "../atoms/LoginButton";
import { useEffect, useState, useRef } from "react";
const LoginForm = () => {
const [submitData, setSubmitData] = useState(null);
const selectInput = useRef(null);
const loginHandler = (e) => {
e.preventDefault();
const { uid, upw } = e.target;
setSubmitData({ uid: uid.value, upw: upw.value });
};
useEffect(() => {
console.log(selectInput.current);
console.log(selectInput.current.value);
if (submitData) console.log(submitData);
}, [submitData, selectInput]);
return (
<form onSubmit={loginHandler}>
<LoginLabel>아이디</LoginLabel>
<LoginInput name={"아이디"} type={"text"}></LoginInput>
<LoginLabel>비밀번호</LoginLabel>
<LoginInput name={"비밀번호"} type={"password"}></LoginInput>
<LoginLabel>아이디(useRef)</LoginLabel>
<input ref={selectInput} value={"123456"} />
<LoginButton>로그인 하기</LoginButton>
</form>
);
};
export default LoginForm;
※ 자주 사용하는 기능들을 hook으로 작성해 재사용해보기!
※ atoms 디자인패턴사용해서 atoms, moecules 나눠서 작성하기
'React' 카테고리의 다른 글
React - learn - Thinking in React (1) | 2023.12.06 |
---|---|
React - pair coding (login, board CRUD) (0) | 2023.12.01 |
React - React Router Hook, Styled Component, HOC, Atomic Pattern (1) | 2023.11.30 |
React - learn - Updating Objects in State, Updating Arrays in State (객체, 배열로 상태 업데이트하기) (0) | 2023.11.29 |
React - learn - Queueing a Series of State Updates (상태 업데이트 대기열에 추가하기) (0) | 2023.11.29 |