[React Native] 처음 배우는 리액트 네이티브 7장

나경·2025년 1월 23일

전역 상태 관리

props로 데이터를 전달하는 방법은 번거로울 수 있다 관리하는 상태가 변경되면 과정에 속하는 모든 컴포넌트를 수정해야 한다

이 때 Context API를 사용하면 중간 과정에 있는 컴포넌트를 거치지 않아도 한번에 원하는 데이터를 받아와서 사용할 수 있다

Context API

const Context = createContext(defaultValue);

Context 오브젝트에는 입력된 기본값 외에도 Consumer 컴포넌트와 Provider 컴포넌트를 가진다

Consumer

Consumer 컴포넌트는 상위 컴포넌트 중 가장 가까운 곳에 있는 Provider 컴포넌트가 전달하는 데이터를 이용한다

상위 컴포넌트 중 Provider 컴포넌트가 없으면
createContext 함수의 파라미터로 전달된 기본값을 사용한다

// contexts/User.js

import { createContext } from "react";

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

export default UserContext;
// components/User.js

import React from 'react'
import { styled } from 'styled-components/native';
import UserContext from '../contexts/User';

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

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

export default User

Provider

하위 컴포넌트에 Context의 변화를 알리는 역할을 한다

  1. value를 받아서 모든 하위 컴포넌트에 전달하고
  2. 하위 컴포넌트는 Provider 컴포넌트의 value가 변경될 때마다 다시 렌더링된다
import React from 'react';
import styled from 'styled-components/native';
import User from './components/User';
import UserContext from './contexts/User';

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

const App = () => {

    return (
        <UserContext.Provider value={{name: 'Nakyeong'}}>
            <Container>
                <User />
            </Container>            
        </UserContext.Provider>
    )
}

export default App

기본값이 아니라 Provider 컴포넌트의 value값이 잘 나타나는 것을 확인할 수 있다

// components/User.js

import React from 'react'
import { styled } from 'styled-components/native';
import UserContext from '../contexts/User';

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

const User = () => {
    return (
        <UserContext.Provider value={{name: 'React Native'}}>
            <UserContext.Consumer>
                {value => <StyledText>Name: {value.name}</StyledText>}
            </UserContext.Consumer>            
        </UserContext.Provider>

    )
}

export default User


하위 컴포넌트가 여러 개 올 수도 있다
따라서 만약 자식 컴포넌트 중 Provider 컴포넌트가 있다면 그 이후의 자식 컴포넌트는 중간에 있는 Provider 컴포넌트의 값을 사용한다

중요한 점
1. Provider 컴포넌트에 반드시 value 지정
2. Consumer 컴포넌트는 가장 가까운 Provider 컴포넌트의 값을 이용

Context 수정하기

  • UserProvider: 하위 Consumer 컴포넌트의 자식 함수 파라미터로 데이터와 데이터 변경하는 함수를 전달
  • createContext: UserProvider 컴포넌트의 형태와 동일하게 사용
// contexts/User.jx

import { createContext, useState } from "react";

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

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

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

const UserConsumer = UserContext.Consumer;

export {UserProvider, UserConsumer};
export default UserContext;
import React from 'react';
import styled from 'styled-components/native';
import User from './components/User';
import { UserProvider } from './contexts/User';

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

const App = () => {

    return (
        <UserProvider> // value 전달하지 않아도 됨
            <Container>
                <User />
            </Container>            
        </UserProvider>
    )
}

export default App
// components/User.js

import React from 'react'
import { styled } from 'styled-components/native';
import UserContext from '../contexts/User';
import { UserConsumer } from '../contexts/User';

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

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

    )
}

export default User


세터 함수를 이용해서 입력된 값으로 Context 값을 변경할 수도 있다

// components/Input.js

import React, { useState } from 'react'
import { styled } from 'styled-components/native'
import { UserConsumer } from '../contexts/User'

const StyledInput = styled.TextInput`
    border: 1px solid #606060;
    width: 250px;
    padding: 10px 15px;
    margin: 10px;
    font-size: 24px;
`

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>
    )
}

export default Input

useContext

Consumer 컴포넌트를 사용하지 않고 Context 내용을 바꿀 수 있게 해주는 Hook이다

// components/User.js

import React, { useContext } from 'react'
import { styled } from 'styled-components/native';
import UserContext from '../contexts/User';
import { UserConsumer } from '../contexts/User';

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

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

export default User
// components/Input.js

import React, { useState } from 'react'
import { styled } from 'styled-components/native'
import { UserConsumer } from '../contexts/User'
import UserContext from '../contexts/User'

const StyledInput = styled.TextInput`
    border: 1px solid #606060;
    width: 250px;
    padding: 10px 15px;
    margin: 10px;
    font-size: 24px;
`

const Input = () => {

    const [name, setName] = useState('');
    const {dispatch} = UserContext(UserContext);

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

export default Input


참고
처음 배우는 리액트 네이티브

0개의 댓글