bestsource

리액트 및 타입 스크립트:컨텍스트 기본값 회피

bestsource 2023. 2. 18. 20:45
반응형

리액트 및 타입 스크립트:컨텍스트 기본값 회피

React, TypeScript, Context/Hooks를 더 잘 익히기 위해 간단한 ToDo 앱을 만들고 있습니다.다만, 콘텍스트를 번거롭게 하기 위해서 필요한 코드가 있습니다.

예를 들어 Todo의 내용을 변경하려면 세 곳(ITodo 인터페이스, 기본 컨텍스트 값, 기본 상태 값)에서 Todo를 변경해야 합니다.새로운 것을 전하려면 , 3 장소(ToDoContext, ToDoContext의 디폴트치, value=)에서 전해야 합니다.코드를 그렇게 많이 쓰지 않아도 되는 더 좋은 방법이 있을까요?

import React from 'react'

export interface ITodo {
    title: string,
    body?: string,
    id: number,
    completed: boolean
}

interface TodoContext {
    todos: ITodo[],
    setTodos: React.Dispatch<React.SetStateAction<ITodo[]>>
}

export const TodoContext = React.createContext<TodoContext>({
    todos: [{title: 'loading', body: 'loading', id: 0, completed: false}],
    setTodos: () => {}
})

export const TodoContextProvider: React.FC<{}> = (props) => {
    const [todos, setTodos] = React.useState<ITodo[]>([{title: 'loading', body: 'loading', id: 0, completed: false}])

    return (
        <TodoContext.Provider value={{todos, setTodos}}>
            {props.children}
        </TodoContext.Provider>
    )
}

인터페이스와 런타임 값의 선언을 피할 방법은 없습니다. 왜냐하면 TS의 유형은 런타임에 사라지기 때문에 런타임 값만 남게 됩니다.한쪽을 다른쪽에서 생성할 수 없습니다.

단, 이 콘텍스트에 액세스 할 수 있는 것은, 이 콘텍스트에 액세스 하는 것 뿐인 것을 알고 있는 경우입니다.TodoContextProvider초기화를 피할 수 있는 컴포넌트TodoContext조금 부정행위를 하고 TS에게 당신이 건네준 건 괜찮다고 말하는 것만으로요.

const TodoContext = React.createContext<TodoContext>({} as TodoContext)

항상 액세스 할 수 있는 것은, 반드시, 의 컨텍스트에만 액세스 해 주세요.TodoContextProvider어디에todos그리고.setTodos로 작성됩니다.useState그러면 초기화를 건너뛸 수 있습니다.TodoContext의 내부에createContext그 초기값은 실제로 접근되지 않을 것이기 때문입니다.

리액션 문서의 주의:

defaultValue 인수는 트리에서 컴포넌트 위에 일치하는 공급자가 없는 경우에만 사용됩니다.

디폴트값이 다음과 같이 지정되는 것이 좋습니다.undefined

const TodoContext = React.createContext<ITodoContext | undefined>(undefined)

그런 다음 콘텍스트를 사용하기 위해 후크를 작성합니다.

function useTodoContext() {
  const context = useContext(TodoContext)
  if (context === undefined) {
    throw new Error("useTodoContext must be within TodoProvider")
  }

  return context
}

왜 이 방법을 좋아할까?즉석에서 내 콘텍스트의 가치가 왜undefined.

자세한 것은, Kent C의 블로그 투고를 봐 주세요. 도드

시간이 좀 흐른 후, 최선의 방법을 찾은 것 같아요.

import React from 'react'

export interface ITodo {
    title: string,
    body?: string,
    id: number,
    completed: boolean
}

const useValue = () => {
    const [todos, setTodos] = React.useState<ITodo[]>([])

    return {
        todos,
        setTodos
    }
}

export const TodoContext = React.createContext({} as ReturnType<typeof useValue>)

export const TodoContextProvider: React.FC<{}> = (props) => {
    return (
        <TodoContext.Provider value={useValue()}>
            {props.children}
        </TodoContext.Provider>
    )
}

이렇게 하면, 본래의 3중 전환점이 아니라, 새로운 것을 컨텍스트에 추가할 때 단일 전환점이 있습니다.맛있게 드세요!

제 상황은 당신과는 조금 다를 수 있지만(이미 인정된 답변이 있다는 것을 알고 있습니다), 현재로서는 이 방법이 효과가 있는 것 같습니다.위 Aron의 답변에서 수정한 것은 그 기술을 사용하는 것이 제 경우에는 효과가 없었기 때문입니다.

내 실제 상황의 이름은 물론 다르다.

export const TodoContext = createContext<any>({} as any)

언급URL : https://stackoverflow.com/questions/61333188/react-typescript-avoid-context-default-value

반응형