[리액트 네이티브] ContextAPI, Consumer, Provider 실습
my code archive
article thumbnail
반응형

🤍Context API란

  • 데이터를 전역적으로 관리하고 사용할 수 있도록 하는 기능

🤍전역 상태 관리

일반적인 흐름 / ContextAPI 흐름

  • 일반적인 리액트 네이티브(React-Native) 애플리케이션의 데이터는 부모 컴포넌트에서 자식 컴포넌트로 전달됨.
  • 예를 들어, 어떤 데이터를 App 컴포넌트에서 관리할 경우, App 컴포넌트로부터 데이터를 필요로 하는 컴포넌트까지 props를 통해 값을 전달해 사용함. -> 하지만 props를 사용하는 방법은 번거로움. (관리하는 상태가 추가, 변경될 경우 과정에 속한 모든 컴포넌트를 찾아 수정해야함.)
  • 이때, Context API를 생성하면 중간 과정에 있는 컴포넌트들을 거치지 않고 한 번에 원하는 데이터를 바로 받아와서 사용할 수 있다.

🤍Context API 실습

expo init react-native-context //프로젝트 생성
npm install styled-components //스타일드 컴포넌트 설치

전체 프로젝트 구조

1. Context API 생성

const Context = createContext(defaultValue);	//예시 코드

User 컴포넌트 작성

import {createContext} from 'react';

const UserContext = createContext({name: 'codeArchive'});

export default UserContext;

2. Consumer

  • Context 오브젝트는 기본값 이외에, Consumer 컴포넌트, Provider 컴포넌트를 갖고 있다.
  • Consumer 컴포넌트는 상위 컴포넌트 중 가장 가까운 곳에 있는 Provider 컴포넌트가 전달하는 데이터를 이용함. 만약 Provider 컴포넌트가 없을 시, createContext 함수의 파라미터로 전달된 기본값을 사용함.
import React from "react";
import styled from "styled-components";
import UserContext from "../contexts/User";

const StyledText = styled.Text`
    font-size: 24px;
    margin: 18px;
`;

 const User = () => {
     return (
             <UserContext.Consumer>
                 {value => <StyledText>Name: {value.name}</StyledText>}
             </UserContext.Consumer>
     );
 };
 
 export default User;

User 컴포넌트를 App 컴포넌트에서 사용해보기

import React from "react";
import styled from "styled-components";
import User from "./components/User";
import UserContext from "./contexts/User";

const Container = styled.View`
    flex: 1;
    background-color: #ffffff;
    justify-content: center;
    align-items: center;
`;

const App = () => {
    return (
        <Container>
            <User />
        </Container>
    );
};

export default App;

📱안드로이드 스튜디오 애뮬레이터로 실행 화면 확인

3. Provider

  • 하위 컴포넌트에 Context의 변화를 알리는 역할 수행.
  • value를 받아 모든 하위 컴포넌트에 전달, 하위 컴포넌트는 Provider 컴포넌트의 value 변경 시마다 다시 랜더링됨.
const App = () => {
    return(
        <UserContext.Provider>
            <Container>
                <User />
            </Container>
    	</UserContext.Provider>
    );
   
};

위와 같이 코드를 작성할 경우, TypeError가 남.

 

💡이유 : App 컴포넌트를 Provider 컴포넌트로 감쌌기 때문에 User 컴포넌트에서 사용된 Consumer 컴포넌트는 더이상 Context의 기본값을 사용할 필요 없이, 상위 컴포넌트인 Provider 컴포넌트가 전달하는 데이터를 사용하도록 변경되었음. 그러나 Provider 컴포넌트에서는 어떤 값도 전달되지 않았으므로 undefined가 전달됨.

다음과 같이 수정 필요함.

<UserContext.Provider value={{name:'CodeArchive'}}>

4. Context 수정하기

-Context 값을 수정해서 Context를 사용하는 컴포넌트에 변경된 내용을 반영해 보기

 

  • Provider 컴포넌트의 value에 전역적으로 관리할 상태 변수, 상태 변경 함수를 함께 전달하는 UserProvider 컴포넌트 생성
  • UserProvider 컴포넌트는 기존 Provider 컴포넌트와 사용법 동일하나, 하위 Consumer 컴포넌트의 자식 함수의 파라미터로 데이터 뿐만 아니라 데이터를 변경할 수 있는 함수도 함께 전달함.
  • Consumer 컴포넌트의 상위 컴포넌트에 Provider 컴포넌트가 없더라도 동작에 문제가 생기지 않도록 형태를 동일하게 맞추는 것이 좋음.
import React, { createContext, useState } from "react";

//const UserContext = createContext({name: 'CodeArchive'});

const UserContext = createContext({
    user: {name: ''},
    dispatch: () => {},
});

const UserProvider = ({children}) => {
    const [name, setName] = useState('jungahzzzang');

    const value = {user: {name}, dispatch: setName};
    return <UserContext.Provider value={value}>{children}</UserContext.Provider>;
};

const UserConsumer = UserContext.Consumer;

export {UserProvider, UserConsumer};
export default UserContext;

User 컴포넌트에서 새로 전달되는 value를 사용하도록 수정.

const User = () => {
    return (
        <UserConsumer>
            {({user})=><StyledText>Name: {user.name}</StyledText>}
        </UserConsumer>
    );
};

📱안드로이드 스튜디오 애뮬레이터로 실행 화면 확인

-Provider 컴포넌트에서 전달되는 value의 형태가 변경되었으므로 새로 전달되는 값에 맞게 수정됨.

5. Input 컴포넌트 만들기

UserProvider 컴포넌트의 value로 전달되는 세터 함수를 이용해 입력되는 값으로 Context의 값을 변경하는 Input 컴포넌트 작성

  • useState 함수를 이용해 name 상태 변수 생성
  • TextInput 컴포넌트에 값 변경 시마다 name에 반영되도록 작성
  • UserConsumer 컴포넌트의 자식 함수에 전달되는 value에는 Context 값을 변경할 수 있는 dispatch가 함께 전달됨. (=키보드 확인 버튼을 누르면 TextInput 컴포넌트에 입력된 값으로 Context 값 변경
const Input = () => {
    const [name, setName] = useState('');

    return(
        <UserConsumer>
            {({dispatch})=>{
                return(
                    <StyledInput
                        value={name}
                        onChangeText={text=>setName(text)}
                        onSubmitEditing={()=>{
                            dispatch(name);
                            setName('');
                        }}
                        placeholder="Enter a name..."
                        autoCapitalize="none"
                        autoCorrect={false}
                        returnKeyType="done"
                    />
                );
            }}
        </UserConsumer>
    );
};

📱안드로이드 스튜디오 애뮬레이터로 실행 화면 확인

반응형
profile

my code archive

@얼레벌레 개발자👩‍💻

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!

반응형