본문 바로가기

Web Tech/react

react 기본 - 18.Context API 로 전역 값 관리

Context API

여러개의 컴포넌트를 거쳐서 전달할 때 사용하면 복잡한 구조를 해결 할 수 있습니다.

Context 기본문법

// 내보내주기
export const UserDispatch = React.createContext(null);

// 사용때 불러오기 
import { UserDispatch } from './App';
// createContext의 파라미터에 Context의 기본값을 설정할 수 있으며,
// 값을 따로 지정하지 않을 경우 사용되는 기본 값
const UserDispatch = React.createContext(null);

// Context를 생성하면, Context 안에 Provider라는 컴포넌트가 들어가있음
// 이 컴포넌트를 통하여 Context의 값을 정할 수 있으며, value 라는 값 설정
<UserDispatch.provider value={dispatch}>...</UserDispatch.Provider>

UserList.js

import React,{useContext} from 'react';
import {UserDispatch} from "./App";

const User = React.memo(function User({user}) {
    const dispatch = useContext(UserDispatch);
    return(
        <>
            <p>
                <b onClick={() => {dispatch({type:'TOGGLE_USER', id:user.id});}} style={{cursor:'pointer', color: user.active ? 'green' : 'black'}}>{user.username}</b>"{user.email}"
                <button onClick={() => {dispatch({type:'REMOVE_USER', id: user.id});}} type="button">삭제</button>
            </p>
            {user.username}
        </>
    )
});

function UserList({users}) {
    return (
        <>
            {users.map(user => (
                <User user={user} key={user.id} />
            ))}
        </>
    )
}

export default React.memo(UserList);

CreateUser.js

import React, {useContext, useRef} from 'react';
import {UserDispatch} from "./App";
import useInputs from "./hooks/useInputs";

const CreateUser = () => {
    const [{ username, email }, onChange, reset] = useInputs({
        username: '',
        email: ''
    });
    const nextId = useRef(4);
    const dispatch = useContext(UserDispatch);

    const onCreate = () => {
        dispatch({
            type: 'CREATE_USER',
            user: {
                id: nextId.current,
                username,
                email
            }
        });
        reset();
        nextId.current += 1;
    }

    return (
        <>
            <input name="username" onChange={onChange} value={username} placeholder="계정명" type="text"/>
            <input name="email" onChange={onChange} value={email} placeholder="계정명" type="text"/>
            <button onClick={onCreate} type="submit">등록</button>
        </>
    )
}

export default React.memo(CreateUser);

App.js

import React, { useRef, useReducer, useMemo, useCallback } from 'react';
import Inner from "./Inner";
import UserList from './UserList';
import CreateUser from './CreateUser';
import useInputs from './hooks/useInputs';

function countActiveUsers(users) {
    console.log('활성 사용자 수를 세는중...');
    return users.filter(user => user.active).length;
}

const initialState = {
    users: [
        {
            id: 1,
            username: 'velopert',
            email: 'public.velopert@gmail.com',
            active: true
        },
        {
            id: 2,
            username: 'tester',
            email: 'tester@example.com',
            active: false
        },
        {
            id: 3,
            username: 'liz',
            email: 'liz@example.com',
            active: false
        }
    ]
};

function reducer(state, action) {
    switch (action.type) {
        case 'CREATE_USER':
            return {
                users: state.users.concat(action.user)
            };
        case 'TOGGLE_USER':
            return {
                ...state,
                users: state.users.map(user =>
                    user.id === action.id ? { ...user, active: !user.active } : user
                )
            };
        case 'REMOVE_USER':
            return {
                ...state,
                users: state.users.filter(user => user.id !== action.id)
            };
        default:
            return state;
    }
}

// UserDispatch 라는 이름으로 내보내줌
export const UserDispatch = React.createContext(null);

function App() {
    const [state, dispatch] = useReducer(reducer, initialState);

    const { users } = state;

    const count = useMemo(() => countActiveUsers(users), [users]);
    return (
        <UserDispatch.Provider value={dispatch}>
            <React.Fragment>
                <Inner>
                    <CreateUser />
                    <UserList users={users} />
                    <p>활성사용자 수 : {count}</p>
                </Inner>
            </React.Fragment>
        </UserDispatch.Provider>
    );
}

export default App;

'Web Tech > react' 카테고리의 다른 글

React 기본 - 2.리액트 환경설정 및 시작하기  (0) 2022.01.11
React 기본 - 1.리액트란?  (0) 2022.01.11
react 기본 - 17.커스텀 Hooks  (0) 2021.12.06
react 기본 - 16.useReducer  (0) 2021.11.30
react 기본 - 15.React.memo  (0) 2021.11.30