Context API를 이용하면 전역으로 상태를 관리해야 하는 상황에서 props를 일일이 전달하지 않아도 원하는 컴포넌트에서 해당 데이터를 이용할 수 있다.
컨텍스트 API를 사용할 때 가장 먼저 호출되는 함수는 createContext이다. 컨텍스트를 생성하는 함수로 파라미터의 기본값을 전달하고 createContext함수에 전달되는 기본 값은 적절한 provider을 찾지 못했을 떄 사용한는 값이다.
const Context = createContext(기본값)
import {createContext} from 'react';
const Context = createContext({
name:'Beomjun',
setName: ()=>{}
})
Provider 컴포넌트의 역할은 context의 변화를 하위 컴포넌트들에게 알리는 역할이다. React Native에서
ThemProvider컴포넌트도 Context ApI의 Provider 컴포넌트이다.
<Provider value={}>
...
</Provider>
Consumer 컴포넌트의 역할은 부모 컴포넌트 중에서 가장 가까이 있는 Provider 컴포넌트가 전달하는 데이터를 받아서 이용하는 역할이다.
<Consumer>
{value=> ...}
</Consumer>
<Provider value={}>
<Consumer>
</Consumer>
</Provider>
<Provider1 value={}>
<Consumer1> // => Consumer1은 Provider1이 제공하는 데이터 이용
<Provider2 value={}>
<Consumer2>// => Consumer2은 Provider2이 제공하는 데이터 이용
</Consumer2>
</Provider2>
</Consumer1>
</Provider1>
예시 코드
import React, { createContext } from 'react';
...
const App2 = () => {
//사용자의 정보를 관리하는 context 제작. 기본 값은 객체 형태
const UserContext = createContext({ name: 'gyduddl' });
return (
// 기본값으로 설정된 데이터의 모양(key값이 같아야 하는듯)과
//provider value로 설정된 모양이 일치해야 한다.
<UserContext.Provider value={{ name: 'gyduddl kim' }}>
<Container>
{/* //consumer 컴포넌트를 이용해 comsumer 컴포넌트의 자식으로 데이터 전달 */}
<UserContext.Consumer>
{(value) => <StyledText>{value.name}</StyledText>}//=>출력'gyduddl kim'
</UserContext.Consumer>
<UserContext.Provider value={{ name: 'gyduddl222' }}>
<UserContext.Consumer>
{(value) => <StyledText>{value.name}</StyledText>} //=>출력 : 'gyduddl222'
</UserContext.Consumer>
</UserContext.Provider>
</Container>
</UserContext.Provider>
);
};
const Context = createContext(기본값)
<Consumer>
</Consumer>
Hook 중에서 useContext를 이용하면 Context API를 더 편하게 이용할 수 있다. useContext를 이용하면 Provider 컴포넌트가 전달하는 데이터를 굳이 Consumer 컴포넌트를 이용하지 않더라도 Context를 받아와서 사용할 수 있다.
const 데이터 = useContext(Context)
//contexts/User.js
import React, { createContext, useState } from 'react';
//createContext를 이용해서 context를 만듬
const UserContext = createContext({
name: '',
setName: () => {},
});
//매번 context에 provider을 접근해서 사용하지 않도록
//userProvider 컴포넌트 만듬
const UserProvider = ({ children }) => {
//사용자의 이름을 관리하는 상태 변수(기본값설정)
const [name, setName] = useState('gyduddl');
//povider의 value로 설정할 value는 name과 setName을 갖고 있도록 설정
const value = { name, setName };
//provider 컴포넌트의 자식 컴포넌트로 들어오는 컴포넌트들을 children을 이용해서 렌더링
return <UserContext.Provider value={value}>{children}</UserContext.Provider>;
};
const UserConsumer = UserContext.Consumer;
//외부에서도 사용할 수 있도록 export
export { UserProvider, UserConsumer };
export default UserContext;
//components/User.js
import React from 'react';
import styled from 'styled-components/native';
import { UserConsumer } from '../contexts/User';
const StyledText = styled.Text`
font-size: 30px;
font-weight: 600;
`;
const User = () =>{
return(
<UserConsumer>
{({name})=> <StyledText>Name:{name}</StyledText>}
</UserConsumer>
)
}
export default User;
//components/User.js
import React, { useState } from 'react';
import styled from 'styled-components/native';
import { UserConsumer } from '../contexts/User';
const StyledText = styled.Text`
font-size: 30px;
font-weight: 600;
`;
const StyledInput = styled.TextInput`
border: 1px solid #111111;
font-size: 26px;
padding: 10px;
width: 100%;
`;
const User = () => {
const [text, setText] = useState('');
return (
<>
{/* 버전 1. */}
{/* <UserConsumer>{({ name }) => <StyledText>Name:{name}</StyledText>}</UserConsumer>
<UserConsumer>
{({ setName }) => (
<StyledInput
value={text}
onChangeText={setText}
onSubmitEditing={() => {
setName(text);
setText('');
}}
/>
)}
</UserConsumer> */}
{/* 버전 2. */}
<UserConsumer>
{({ name, setName }) => (
<>
<StyledText>Name:{name}</StyledText>
<StyledInput
value={text}
onChangeText={setText}
onSubmitEditing={() => {
setName(text);
setText('');
}}
/>
</>
)}
</UserConsumer>
</>
);
};
export default User;
//components/User.js
import React, { useState, useContext } from 'react';
import styled from 'styled-components/native';
import UserContext from '../contexts/User';
const StyledText = styled.Text`
font-size: 30px;
font-weight: 600;
`;
const StyledInput = styled.TextInput`
border: 1px solid #111111;
font-size: 26px;
padding: 10px;
width: 100%;
`;
const User = () => {
const [text, setText] = useState('');
//useContext를 이용해서 데이터를 받아오는데 useContext에 전달되어야 되는 값은
//provider이나 consumer이 아닌 context 자체가 전달되어야 한다.
const { name, setName } = useContext(UserContext);
return (
<>
<StyledText>Name:{name}</StyledText>
<StyledInput
value={text}
onChangeText={setText}
onSubmitEditing={() => {
setName(text);
setText('');
}}
/>
</>
);
};
export default User;
확실히
useContext를 사용하여Consumer을 사용하지 않고 상태관리를 하니 코드가 훨씬 직곤적이고 사용하기 편해졌다.