7장. Context API

두더지·2024년 2월 12일
0

[처음 배우는 리액트 네이티브] 책을 공부하면서 정리한 내용입니다.

Context API

: 데이터를 전연적으로 관리하고 사용할 수 있도록 하는 기능
부모-자식 컴포넌트로 연결되어 있는 흐름상, 하위 컴포넌트에서 데이터를 요청하고 수정할 때, 건너가야하는 컴포넌트들이 많아 불편하다. 이때, Context API를 이용하면 Context를 생성해 필요한 컴포넌트에서 데이터를 바로 받아올 수 있다.

ex.

const Context = createContext(defaultValve);

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

Consumer 컴포넌트

: 상위 컴포넌트 중 가장 가까운 곳에 있는 Provider 컴포넌트가 전달하는 데이터 이용.
만약, 상위 컴포넌트 중 Provider 컴포넌트가 없다면, 기본값 사용.

  • src/contexts/User.js
import { createContext } from 'react';

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

export default UserContext;
  • src/conponents/User.js
import React from 'react';
import UserContext from '../contexts/User';

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

export default User;

-src/App.js

import User from './components/User';
...

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

Provider 컴포넌트

: 하위 컴포넌트에 Context의 변화를 알리는 역할.
value를 받아서 모든 하위 컴포넌트에 전달하고, 하위 컴포넌트들은 이때마다 렌더링 됨.

-src/App.js

import User from './components/User';
...

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

이렇게 수정한 경우, 오류 메세지가 나온다.
이유 : App 컴포넌트를 Provider 컴포넌트로 감쌌기 때문에 User 컴포넌트에서 사용된 Consumer 컴포넌트는 더이상 Context의 기본값이 아닌 상위 컴포넌트인 Provider 컴포넌트가 전달하는 데이터를 사용하도록 변경. 하지만 아무것도 전달되지 않았기 때문.

import User from './components/User';
...

const App = () => {
	return (
    	<UserContext.Provider value={{ name: 'Jeesoo' }}>
    		<Container>
        		<User />
        	</Container>
        </UserContext.Provider>
    );
};

이렇게 값을 전달해주면 잘 작동한다.

또한, Consumer 컴포넌트는 가장 가까운 Provider 컴포넌트가 전달하는 값을 이용한다.
(Provider 컴포넌트로부터 전달받는 하위 컴포넌트 수에는 제한이 없음.)

context 수정

-src/context/User.js

import React, { createContext, useState } from 'react';

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

const UserProvider = ({ children }) => {
	const [name,setName] = useState('Jeesoo Kim');
    
    const value = { user: { name }, dispatch: setName };
    return <UserContext.Provider value={value}>{children}</UserContext.Provider>; 
};

const UserConsumer = UserContext.Consumer;

export { UserProvider, UserConsumer };
export default UserContext;

UserProvider 컴포넌트 : Provider 컴포넌트의 value에 전역적으로 관리할 useState를 함께 전달.
하위에 있는 Consumer 컴포넌트의 자식 함수의 파라미터로 데이터와 데이터를 변경할 수 있는 함수까지 전달.
createContext의 기본값 형태도 UserProvider 컴포넌트의 value로 전달하는 형태와 동일.

-src/components/Input.js

import React, { useState } from 'react';
import {UserConsumer } from '../contexts/User';

const Input = () => {
	const [name, setName] = useState('');
    return (
    	<UserConsumer>
        	{({ dispatch }) => {
            	return (
                	<TextInput
                      value={name}
                      onChangeText={text => setName(text)}
                      onSubmitEditing={() -> {
                      	dispatch(name);
                        setName('');
                      }}
                      placeholder="Enter a name..."
                      autoCapitalize="none"
                      autoCorrect={false}
                      returnKeyType="done"
                     />
                 );
             }}
         </UserConsumer>
     );
};

export default Input;

useState 함수를 통해 name 상태변수를 생성.
TextInput 컴포넌트에 값이 변경될 때마다 name에 반영.
UserConsumer 컴포넌트의 자식 함수에 전달되는 value에는 Context의 값을 변경할 수 있는 dispatch 함수가 함께 전달되고, dispatch 함수를 통해 키보드의 확인 버튼을 누르면 입력된 값으로 Context의 값 변경.

useContext

: Consumer 컴포넌트의 자식 함수로 전달되던 값과 동일한 데이터 반환.
즉, Consumer 컴포넌트를 사용하지 않고 Context의 내용을 사용 가능하게 함.

위의 코드를 useContext를 사용하는 코드로 수정.

-src/components/User.js

import React, { useContext } from 'react';
import UserContext from '../contexts/User';

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

export default User;

-src/components/Input.js

import React, { useState, useContext } from 'react';
import {UserConsumer } from '../contexts/User';
import UserContext from '../contexts/User';

const Input = () => {
	const [name, setName] = useState('');
    const { dispatch } = useContext(UserContext);
    
    return (
    	<TextInput
         value={name}
         onChangeText={text => setName(text)}
         onSubmitEditing={() -> {
         	dispatch(name);
            setName('');
         }}
		 placeholder="Enter a name..."
         autoCapitalize="none"
         autoCorrect={false}
         returnKeyType="done"
        />
    );
};

export default Input;
profile
컴공생의 밍기적

0개의 댓글