<< 학습 목표 >>

1. 컴포넌트 간 데이터를 주고 받기 위해 useContext 훅을 사용할 수 있다.


전 글 ( https://codingaja.tistory.com/84 ) 에서 컴포넌트간에 데이터를 주고 받기 위해 사용한 방식을 useContext 훅을 사용한 방식으로 바꿔보자

글의 제목은 개선이라고 썼지만 프로젝트의 컴포넌트 트리가 간단하므로 개선이라기 보단 바꾼다 가 더 적합함

 

우선 코드를 모두 입력하고 설명을 보자

<< AddressMng 컴포넌트 >>

더보기

import React, {useState} from 'react';
import AddressAdd from './AddressAdd';
import AddressList from './AddressList';

export const AddressContext = React.createContext();

function AddressMng() {
    const [address, setAddress] = useState();

    return(
        <div className="container">
            <div className="text-center">
                <h1>[ 주소록 관리 프로젝트 (useContext) ]</h1>
                <hr />
            </div>

            <AddressContext.Provider value={ {address, setAddress} }>
                <AddressAdd />

                <AddressList/>
            </AddressContext.Provider>
        </div>
    );
}

export default AddressMng;

<< AddressAdd 컴포넌트 >>

더보기

import React, {useRef, useContext} from 'react';
import { AddressContext } from './AddressMng';

function AddressAdd() {
    let nameRef = useRef(null);
    let telRef = useRef(null);
    let addressRef = useRef(null);
    const setAddress = useContext(AddressContext).setAddress;

    let clickAddBtn = () => {
        let address = {
            "name": nameRef.current.value,
            "tel": telRef.current.value,
            "address": addressRef.current.value
        }

        setAddress(address);
    }

    return(
        <div id="add_panel">
            <div className="row align-items-center justify-content-center">
                <div className="col-2">
                    <input type="text" className="form-control" placeholder="이름" ref={nameRef} />
                </div>
                <div className="col-2">
                    <input type="tel" className="form-control" placeholder="연락처" ref={telRef} />
                </div>
                <div className="col-5">
                    <input type="text" className="form-control" placeholder="주소" ref={addressRef} />
                </div>
                <div className="col-2 text-center">
                    <button type="button" className="btn btn-primary" onClick={clickAddBtn}>추가</button>
                </div>
            </div>
            <hr />
        </div>
    );
}

export default AddressAdd;

<< AddressList 컴포넌트 >>

더보기

import React, {useState, useEffect, useContext} from 'react';
import Address from './Address';
import { AddressContext } from './AddressMng';

function AddressList() {
    const [addressList, setAddressList] = useState([]);
    const address = useContext(AddressContext).address;

    useEffect(() => {
        if(address != null) {
            let newAddressList = Array.from(addressList);
            newAddressList.push(address);
    
            setAddressList(newAddressList);
        }
    }, [address]);

    return(
        <div id="list_panel">
            <table className="table text-center">
                <thead>
                    <tr className="row">
                        <th className="col-1" scope="col"></th>
                        <th className="col-2" scope="col">이름</th>
                        <th className="col-2" scope="col">연락처</th>
                        <th className="col-5" scope="col">주소</th>
                        <th className="col-2" scope="col"></th>
                    </tr>
                </thead>
                <tbody>
                    {
                    addressList.map((address, index) => {
                        return <Address key={index} number={address.number} name={address.name} tel={address.tel} address={address.address} />
                    })
                    }
                </tbody>
            </table>
        </div>
    );
}

export default AddressList

 

<< AddressMng 컴포넌트와 AddressAdd 컴포넌트 설명 >>

더보기

 

(1). 부모 컴포넌트와 자식 컴포넌트들이 공유해서 사용할 Context(공용 변수) 생성

(2). 자식 컴포넌트에서 전달할 값을 받기 위한 변수 선언

(3). 자식 컴포넌트들이 Context를 사용할 수 있도록 설정

(4). 전 글 ( https://codingaja.tistory.com/85 ) 에서는 자식 컴포넌트로 간단하게 "Hi" 문자열을 전달했지만 이번에는 address와 setAddress 를 전달

  address는 주소 정보를 저장할 값이지만 setAddress는 setter 함수라는 점에 유의하자

  JS는 함수가 1급 객체이기 때문에 이와 같이 함수를 전달할 수도 있음

 

  자식 컴포넌트로 값들을 보내기 위해 { } 로 묶었다는 점에도 유의하자

   address는 AddressList 컴포넌트에서 사용하고 setAddress는 AddressAdd 컴포넌트에서 사용함

 

(5). AddressMng 부모 컴포넌트가 전달한 setter 를 꺼내기 위해 공용 변수를 import함

(6). 공용 변수에 들어있는 setter를 꺼내기 위해 우선 useContext 훅을 사용함

  conset setAddress = useContext(AddressContext); 만 하게 되면 setAddress 변수에 address 값을 갖고 있는 변수와 setter 함수가 모두 저장됨, 이와 같이 했다면 setAddress.setAddress(address); 로 해야하기에 좀 더 편하게 사용하기 위해 공용 변수가 갖고 있는 setter 함수만 setAddressd 변수에 저장함

(7). 부모 컴포넌트가 공용 변수에 담아서 보내준 setter 를 사용해서 주소 정보 저장


 

<< AddressList 컴포넌트 설명 >>

더보기

 

(1). AddressMng 부모 컴포넌트가 전달한 공용 변수를 사용하기 위해 import함

(2). 공용 변수 내 address 변수의 값(주소 정보)만 꺼냄

(3). 꺼낸 주소 정보를 주소록에 저장


 

바뀐 부분이 크게 없다고 느끼거나 "왜 굳이 useContext 를 사용하지?" 라고 느낄 수 있음

이 글의 처음에 언급했듯 우리 프로젝트의 규모가 작아서 그런것이므로 여기서 알려준 방법대로 부모 컴포넌트와 자식 컴포넌트가 값을 주고 받는 방법을 잘 기억해두면 포트폴리오 또는 현업에서 도움이 많이 될 것

728x90
LIST