230307- React –

내가 오늘 배운 것

1. 콜백 사용

2. 메모 사용

3. 참고

4. 컨텍스트 사용

5. 감속기 사용

컴포넌트가 렌더링될 때마다 기능 컴포넌트의 경우 상태가 있는 전체 함수가 다시 실행됩니다.

따라서 구성 요소에 많은 논리가 있는 경우 시간이 오래 걸릴 수 있습니다.

구성 요소가 다시 실행되면 구성 요소에 포함된 기능이 다시 빌드됩니다.

변경되지 않는 기능이나 구성 요소를 다시 렌더링하는 동안 불필요한 리소스를 사용하여 많은 낭비가 있을 수 있습니다.

이 문제는 기능적 구성 요소 후크를 사용하여 피할 수 있습니다.

용도는 같지만 반환 값이 다른 UseCallback 및 useMemo 후크를 사용합니다.

사용중 콜백 함수 값반환하고 useMemo의 경우 결과 값보고

1. 콜백 사용

useCallback(함수, (상태)) 반환 값은 함수 값입니다.


콜백은 두 번째 인수의 값인 상태가 변경되는 경우에만 실행됩니다.

암기: 작업이 메모리에 저장되면 값이 검색되어 필요할 때 사용됩니다.

useCallback은 함수 값을 기억하고 해당 함수 값이 변경된 경우에만 함수를 실행하고 그렇지 않으면 기존 함수를 사용합니다.

조건 값을 잘 작성해야 합니다.

비워두면 상태가 트리거되지만 화면에는 표시되지 않습니다.

빈 값을 기억하기 때문입니다.

(함수를 만들 때 처음 0으로 마운트했을 때의 상태가 계속 생각납니다…)
따라서 카운트가 변경되는 시기를 추적할 수 있도록 상태를 카운트로 작성해야 합니다.

함수를 작성할 때 효율적으로 관리할 수 있도록 함수 뒤에 작성하십시오.

//사용 방법

//useCallback 사용전
const increment = () => {
    setCount(count + 1)
}

//useCallback 사용후
const increment = useCallback(() => {
    setCount(count + 1)
}, (count))

2. 메모 사용

`useMemo(()=>{}, (상태))` 이 함수는 상태가 변경되고 결과 값이 반환될 때만 호출됩니다.


반환된 결과 값은 이후 렌더링에서 재사용됩니다.

useCallback은 함수 자체를 저장하여 함수를 다시 생성하지 않고 이전에 생성한 함수를 반환하지만 useMemo는 인수로 받은 함수를 실행한 결과를 기억하고 값이 변경되지 않은 경우 이전에 계산한 값을 반환합니다.


이렇게 하면 값이 변경되지 않은 경우에도 다시 렌더링되지 않을 수 있습니다.

useMemo의 첫 번째 인수로 전달되는 함수는 다음과 같습니다.

계산 결과를 반환합니다.

두 번째 인자로 전달된 배열에 포함된 값이 변경될 때마다 함수가 실행되고 새로운 결과 값이 반환됩니다.

2-1 샘플 코드

import { useState, useMemo } from "react"

export const Memo = () => {
    const (numbers, setNumbers) = useState((1, 2, 3, 4, 5, 6, 7, 8, 9, 10))
    const (value, setValue) = useState(0)

    // useMemo가 있을 때,
    const oddNumbers = useMemo(() => {
        return numbers.filter((v) => {
            console.log("hello Memo")
            return v % 2 !
== 0 }) }, (numbers)) // useMemo가 없을 때, const oddNumbers = numbers.filter((v) => { console.log("hello Memo") return v % 2 !
== 0 }) const handleClick = () => { setNumbers((...numbers, numbers.length + 1)) } return ( <div> <p>숫자 : {numbers.join(", ")}</p> <p>홀수 : {oddNumbers.join(", ")}</p> <button onClick={handleClick}>요소추가</button> <button onClick={() => setValue(value + 1)}>value</button> </div> ) }

useMemo()를 사용하지 않으면 oddNumbers와 관련 없는 값 버튼을 눌러도 “hello Memo”가 표시됩니다.


그러나 useMemo()를 사용하는 경우 값 버튼을 눌러도 숫자가 변경되지 않으므로 “hello Memo”가 인쇄되지 않습니다.

숫자의 상태를 추적하고 있기 때문에 “hello memo”는 숫자의 상태와 관련된 항목을 추가하는 버튼을 눌렀을 때만 실행됩니다.

3. 참고

prop의 내용이나 내용의 결과가 같으면 다시 렌더링하지 않는 방법이 있습니다.

useMemo와 Memo의 차이점은 useMemo는 컴포넌트 내부에 변수를 저장하는 데 사용되지만 Memo는 컴포넌트 자체를 저장한다는 것입니다.

구성 요소의 소품이 변경되지 않은 경우 구성 요소가 변경되지 않았기 때문입니다.

메모로 다시 렌더링하지 않고 이전에 렌더링한 값을 사용합니다.

그러나 구성 요소 내에서 useCallback을 사용하지 않으면 함수의 상태가 변경되고 메모리 주소가 변경될 때마다 새 함수 인스턴스가 생성됩니다.

값이 같더라도 새로운 주소로 인식되기 때문에 메모만으로는 재 렌더링을 막을 수 없습니다.

4. 컨텍스트 사용

props를 사용하여 개별적으로 하위 구성 요소에 상태를 전달하는 것이 가능했지만 전역적으로 상태를 관리하는 구성 요소를 사용하면 상위 구성 요소에서 몇 단계 아래의 구성 요소로 상태 값을 직접 전달할 수 있습니다.

이것을 사용 구성 요소 간에 데이터를 전달하는 오버헤드를 줄이고 상태를 즉시 공유할 수 있습니다.

Redux 라이브러리와 동일하지만 Redux보다 더 많은 기능이 부족합니다.

import { useState, createContext, useContext } from "react"

const Global = createContext()

const D = () => {
    const value = useContext(Global)
    return <>Hello Context : {value}</>
}
const C = () => {
    return <D />
}
const B = () => {
    return <C />
}
const A = () => {
    return <B />
}

export const Context = () => {
    const (user, setUser) = useState("web7722")
    return (
        <Global.Provider value="web7722">
            <A />
        </Global.Provider>
    )
}

값 데이터를 사용하여 Global.provider 구성 요소에 전달할 수 있습니다.

위의 코드에서 전역 상태 데이터를 값에 문자열 형식으로 포함하여 확인했습니다.


이렇게 하나의 데이터 타입만 전달하면 값을 전달하여 사용할 수 있지만 값을 변경할 수는 없으며, 객체를 사용하면 전역적으로 객체를 관리하고 필요한 컴포넌트에서 사용할 수 있다.

import { useState, createContext, useContext } from "react"

const Global = createContext()

const D = () => {
    const obj = useContext(Global)
    return <>Hello Context : {obj.user}</>
}
const C = () => {
    return <D />
}
const B = () => {
    return <C />
}
const A = () => {
    return <B />
}

export const Context = () => {
    const (user, setUser) = useState("web7722")
    const initialState = {
        user,
        setUser,
    }
    return (
        <Global.Provider value={initialState}>
            <A />
        </Global.Provider>
    )
}

위와 같은 방법으로 객체를 이용하여 전역적으로 상태를 관리하고 사용할 수 있었습니다.


그러나 위의 방법을 사용할 경우 각각 관리해야 할 상태 값과 상태를 변경하는 기능이 있기 때문에 관리해야 할 상태 값이 많을 때 문제가 발생한다.

그래서 우리는 useReducer로 이 문제를 해결할 수 있습니다.

5. useReducer

상태의 모든 데이터가 클래스 구성 요소의 setState로 관리되는 것처럼 후크의 함수로 여러 상태를 관리하기 위해 만들어졌습니다.

5-1 상태 변경

this.state = {
    user: {},
    board: {},
    next: false,
}

//방법1. next만 바꾸고 싶을 때,
this.setState({
    ...this.state,
    user: { ...this.state.user },
    board: { ...this.state.board },
    next: true,
})

//방법2. 함수로 다시 빼서
const nextUpdate = {
    ...this.state,
    user: { ...this.state.user },
    board: { ...this.state.board },
    next: true,
}

this.setState(nextUpdate)

클래스 컴포넌트에서는 상태를 하나의 객체로 관리할 수 있지만, 상태를 변경할 때 하나를 변경하려면 다른 상태 값도 함께 변경해야 하는 경우가 있었다.

기능 컴포넌트의 상태 값을 관리하기 위해 useState로 할 수 있지만, 단순한 값을 변경하는 것이 효율적이었지만 복잡한 상태 관리 로직에는 한계가 있었습니다.

이 제한을 수정하려면 `useReducer()`생성 된

5-2 useReducer()

//첫 번째 인자 : (상태값을 바꾸는 함수)
//두 번째 인자 : 초기 상태 값 (대체로 객체형태)
useReducer(function 값, 초기상태값)

const initialState = {}

//reducer 예시
const reducer = (state, action) => {
    console.log("hello reducer")
    console.log(state)

    switch (action.type) {
        case "increment":
            return { count: state.count + action.payload, user: state.user }
        case "decrement":
            return { count: state.count - action.payload, user: state.user }
        default:
            return state
    }
}

const (state, dispatch) = useReducer(reducer, initialState)

Reducer의 기능은 최초 렌더링시 실행되지 않지만 useReducer의 기능은 dispatch가 실행될 때 실행됩니다.

useReducer 첫 번째 인수 값인 함수는 상태 변경 함수로 this.setState와 같은 역할을 합니다.

당신은 말할 수 있습니다

리듀서의 첫 번째 파라미터로 첫 번째 렌더링 시점의 전체 초기 상태를 담고 있습니다.


감속기는 반드시 반품 포함그것은해야한다.

(변경할 상태 값)

dispatch() 인수 값은 일반적으로 객체를 포함합니다.

5-3 감속기()

useReducer 후크에서 상태를 업데이트하는 기능오전.
Reducer() 함수는 두 개의 인수 값을 사용합니다.

첫 번째 상태
두 번째 행동

감속기 함수는 일반적으로 switch 문으로 작성됩니다.

리듀서 함수 내부에서는 state나 action이 변경되어서는 안 되며, 받은 값을 이용하여 새로운 state를 반환하는 로직만 구현되어야 합니다.

스위치에서 조건 하에서 조치 유형의 값에 따라 다른 조치가 수행됩니다.

작업에는 유형이 아닌 페이로드도 있습니다.

페이로드는 문자열, 숫자 문자열, 배열, 객체 등을 포함할 수 있으며 작업에 필요한 추가 데이터를 전달할 수 있습니다.