props로 데이터를 전달하는 방법은 번거로울 수 있다 관리하는 상태가 변경되면 과정에 속하는 모든 컴포넌트를 수정해야 한다
이 때 Context API를 사용하면 중간 과정에 있는 컴포넌트를 거치지 않아도 한번에 원하는 데이터를 받아와서 사용할 수 있다
const Context = createContext(defaultValue);
Context 오브젝트에는 입력된 기본값 외에도 Consumer 컴포넌트와 Provider 컴포넌트를 가진다
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

하위 컴포넌트에 Context의 변화를 알리는 역할을 한다
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 컴포넌트의 값을 이용
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

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

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