본문 바로가기
Framework/React

React Context API

by cariño 2022. 10. 12.
728x90
반응형
  • 처음만난 리액트 강의에서 발췌한 내용입니다.

컴포넌트의 props를 통한 데이터 전달

기존에 일반적인 react application은 데이터가 컴포넌트의 props를 통해 부모가 자식에게 단방향으로 전달이되었다.

로그인여부, 프로필 정보등을 전달하려면 반복적이고 지저분한 코드가 많이 생성된다.
이렇게 여러 컴포넌트에 걸쳐 자주 사용하는 데이터의 경우 코드의 복잡함 등을 해소시켜 주기위해 사용할 수 있는것이 context이다.

Context는 리액트 컴포넌트들 사이에서 데이터를 기존의 props로 전달하는대신
컴포넌트 트리를 통해 곧바로 컴포넌트로 전달해 어떤 컴포넌트던 데이터에 쉽게 접근할 수 있다.
코드를 한 곳에서 관리하기때문에 디버깅에도 유리하다.

 

[언제 context를 사용해야할까?]
로그인 여부, 로그인 정보, UI테마, 현재 언어 등..
nav에서 로그인된 상태의 화면등 context를 사용하면 편리하게 코드를 관리할 수 있다.

 

[단방향 props]

//기존 데이터
function App(props) {
    return <Toolbar theme="dark">
}
▼
function Toolbar(props) {
    return <Button theme={props.theme}>
}
▼
function ThemeButton(props) {
    return <Button theme={props.theme}>
}

 

[Context 사용해보기]

const ThemeContext = React.createContext('light');
  • 컨텍스트는 데이터를 매번 컴포넌트를 통해 전달할 필요 없이 컴포넌트 트리로 곧바로 전달하게 해준다.
  • 여기에서는 테마를 위한 컨텍스트를 생성하며 기본값은 light'

 

 

function App(props) {
    return (
        <ThemeContext.Provider value="dark">
            <Toolbar />
        </ThemeContext.Provider>
    )
}
  • Provider를 사용하여 하위 컴포넌트들에게 현재 테마 데이터를 전달한다.
  • 모든 하위 컴포넌트들은 컴포넌트 트리 하단에 얼마나 깊이 있는지에 관계없이 데이터를 읽을 수 있다.

 

 

function Toolbar(props) {
    return (
        <div>
            <ThemeButton />
        </div>
    )
}
  • 중간에 위치한 컴포넌트는 테마 데이터를 컴포넌트로 전달할 필요가 없다.

 

 

function ThemeButton(props) {
    return (
        <div>
            <ThemeContext.Consumer>
                {value => <Button theme={value}/>}
            </ThemeContext.Consumer>
        </div>
    )
}
  • 리액트는 가장 가까운 상위 테마 Provider를 찾아서 해당되는 값을 사용한다.
  • 해당되는 Provider가 없을 경우 기본값(여기에서는 'Light')를 사용한다.
  • 여기에서는 상위 Provider가 있기 때문에 현재 테마의 값은 'dark'가 된다.

 

 

[고려해야할 점]


컴포넌트왜 context가 연결되면 재사용성이 떨어진다.
데이터를 필요로하는 경우가 아니라면 props composition 방법이 적합하다.

 

import React from 'react'

export default function Page(props) {
    const user = props.user
    const userLink = (
        <Link href={user.permalink}>
            <Avatar user={user} size={props.avatarSize}
        </Link>
    )
    return (
        <PageLayout userLink={userLink}></PageLayout>
    )
}
  • 변수안에 component를 넣었고 해당 변수를 하위 컴포넌트에 전달

 


 

[Context API]

 

컨텍스트 생성

React.createContext(기본값)

렌더링이 일어날때 상위 레벨의 provider부터 받아오는데 Provider가 없으면 기본값이 사용된다.
기본값으로 undefined를 넣으면 기본값이 사용되지 않는다.

 


Context.Provider

<MyContext.Provider value={value}>

하위컴포넌트를 감싸주면 해당 데이터에 접근할 수 있게 된다.

하위컴포넌트는 컨텍스트값의 변경을 지켜보다가 변경이 될 경우 재렌더링된다.

여러개 provider컴포넌트는 중첩될 수 있다.  value prop이 바뀔때마다 재렌더링된다.

 

값의 변화를 판단하는 기준: Object.is (javascript 문서 참고해볼 것)

 

[Provider value에서 주의해야 할 사항]
재렌더링 여부를 결정할 때?
Provider 컴포넌트가 재렌더링될 때마다 모든 하위 consumer컴포넌트가 재렌더링된다.

이를 방지하기 위해서는 value에 값을 직접넣는것이 아닌 state로 넣어줘야 한다.

function App(props){
    return(
        <MyContext.Provider value={{something: 'something'}}>
            <Toolbar />
        </MyContext.Provider>
    )
}
▼
function App(props){
    const [value, setValue] = useState({something: 'something'})
    return(
        <MyContext.Provider value={value}>
            <Toolbar />
        </MyContext.Provider>
    )
}

 

 


3.context.Consumer

function as a child
컴포넌트의 자식으로 함수를 사용하는 방법

<MyContext.Consumer>
    {value => /* 컨텍스트의 값에 따라서 컴포넌트들을 렌더링한다. */}
</MyContext.Consumer>

Consumer로 감싸주면 자식으로 들어간 함수가 현재 컨텍스트의 value를 받아서 리액트 node로 리턴시킨다.
이때 함수로 전달받은 value가 provider의 props value와 동일하다.

만일 상위에 Provider가 없다면 해당 value는 createContext의 기본값과 같다.

728x90

'Framework > React' 카테고리의 다른 글

React Hook Form 회원가입 유효성 체크  (0) 2022.10.24
리액트 CRUD 해보기  (0) 2022.10.22
conditional rendering  (0) 2022.10.11
리액트에서 setState는 비동기로 동작 ??  (1) 2022.10.03
React TodoList 만들기  (0) 2022.10.03

댓글