Notice
Recent Posts
Recent Comments
Link
«   2024/07   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 31
Tags
more
Archives
Today
Total
관리 메뉴

개발공부일지

React - children props, hooks 본문

React

React - children props, hooks

보람- 2023. 12. 4. 16:57

목차

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 나눠서 작성하기