<< 학습 목표 >>

1. 컴포넌트 합성을 사용할 수 있다.


컴포넌트 합성(Composition) 이란 컴포넌트 안에 다른 컴포넌트가 들어가는 것을 뜻함

 

우리가 지금까지 만든 주소록 프로젝트도 컴포넌트 합성을 사용했음

AddressMng 부모 컴포넌트 안에 AddressAdd, AddressList 자식 컴포넌트가 들어있음

 

이와 같은 방법도 컴포넌트 합성이긴 하지만 리엑트에서 말하는 진짜 컴포넌트 합성을 사용해보자

프로젝트 -> src -> chapter04 -> AddressMng.jsx 파일 내 코드를 아래와 같이 수정하자

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

function ProjectTitle(props) {
    return (
    <div className="text-center">
        {props.children}
    </div>
    );
}

function AddressMng() {
    const [addressInfoList, setAddressInfoList] = useState([]);

    function appendAddressInfo(addressInfo) {
        let newAddressInfoList = Array.from(addressInfoList);
        newAddressInfoList.push(addressInfo);

        setAddressInfoList(newAddressInfoList);
    }

    return(
        <div className="container">
            <ProjectTitle>
                <h1>[ 주소록 관리 프로젝트 ]</h1>
                <hr />
            </ProjectTitle>

            <AddressAdd appendAddressInfo={appendAddressInfo} />

            <AddressList addressInfoList={addressInfoList}/>
        </div>
    );
}

export default AddressMng;

<< 코드 설명 >>

컴포넌트 합성을 사용하지 않았을 때와 사용했을 때를 비교 해보면 [ 주소록 관리 프로젝트 ] 라는 프로젝트 타이틀 부분에 컴포넌트 합성을 사용한 것

<< 코드 설명 >>

AddressMng.jsx 파일 내 컴포넌트가 두 개가 됐음

(1). ProjectTitle

(2). AddressMng

AddressMng 컴포넌트는 마지막 줄에 export (3) 하고 있지만 ProjectTitle 컴포넌트는 파일 내 어디에서도 export 를 하고 있지 않음

따라서 AddressMng 컴포넌트는 다른 컴포넌트에서 import 해 출력할 수 있지만 ProjectTItle 컴포넌트는 다른 컴포넌트에서 import 할 수 없음

즉, AddressMng.jsx 파일 내에서만 사용할 컴포넌트 라는 것

 

(1). ProjectTitle 컴포넌트 안을 보면 props.children 을 출력하는데 사용(4)하고 있는데 children 속성은 우리(개발자) 가 props에 넣는게 아니라 리엑트가 props 에 넣어주는 것

(5). ProjectTitle 컴포넌트를 사용했는데 사이에 태그가 들어있음

  이렇게 컴포넌트 사이에 태그가 들어있다면 리엑트는 ProjectTItle 컴포넌트의 props의 children 속성에 사이에 들어있는 태그를 담아서 전달함

 

(1) 에서 컴포넌트 합성을 적용해 컴포넌트를 선언한 것

(5) 에서 컴포넌트 합성이 적용된 컴포넌트를 사용한 것


컴포넌트 합성은 어떻게 활용될까?

주소록 프로젝트의 규모가 작아서 컴포넌트들이 모두 상이함

그러나 포트폴리오처럼 프로젝트 규모가 커지면 컴포넌트 사이에 구조는 같지만 텍스트나 일부만 살짝 달라지는 상황이 자주 발생함

그럴 때 태그를 복사 & 붙여넣기 하는것 보다 컴포넌트 합성을 사용해 구조는 같게 하고 텍스트나 일부가 살짝 달라지는 부분을 props.children 으로 출력하도록 한다면 더 간편하고 효율적으로 컴포넌트를 관리할 수 있음

 

위에서 한 컴포넌트 합성 방법을 Containment 라고 부름

728x90
LIST

<< 학습 목표 >>

1. State 끌어올리기를 구현할 수 있다.


Chapter03 에서 프로젝트를 하며 Context 를 사용해 프로젝트 내 컴포넌트들이 데이터를 공유해 사용하는 방법을 배웠음

이번에는 useState 훅을 사용해 인접한 컴포넌트 사이에 데이터를 공유해 사용하는 방법을 배워보자

 

아래와 같이 부모 컴포넌트는 value 변수를 갖고 있고 value 변수에는 2가 들어있음

자식 컴포넌트 A는 부모 컴포넌트가 갖고 있는 value 변수 값에 2를 곱해 출력하는 컴포넌트

자식 컴포넌트 B는 부모 컴포넌트가 갖고 있는 value 변수 값에 3을 곱해 출력하는 컴포넌트

이런 상황이라면 부모 컴포넌트에서 자식 컴포넌트의 props 로 value 를 전달해 해결할 수 있다는 우리는 걸 잘 알고 있음

이렇게 세 컴포넌트가 하나의 값을 사용하는데 이때 value 변수를 shared state / 공유 변수라고 함

 

공유 변수라는 말이 붙었지만 전혀 새로울 게 없는 내용임


 

Chapter03에서 진행했던 주소록 프로젝트에서 주소록을 추가하는 부분만 지금 배운 공유 변수를 적용한 코드로 바꿔보자

Context와 useEffect가 빠진 훨씬 더 가벼운 프로젝트가 됨

 

코드가 많이 바뀌었으니 프로젝트 -> src -> chapter04 -> AddressMng.jsx 파일을 추가하고 아래 코드를 추가하자

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

function AddressMng() {
    const [addressInfoList, setAddressInfoList] = useState([]);

    function appendAddressInfo(addressInfo) {
        let newAddressInfoList = Array.from(addressInfoList);
        newAddressInfoList.push(addressInfo);

        setAddressInfoList(newAddressInfoList);
    }

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

            <AddressAdd appendAddressInfo={appendAddressInfo} />

            <AddressList addressInfoList={addressInfoList}/>
        </div>
    );
}

export default AddressMng;

<< 코드 설명 >>

(1). 주소록을 저장할 변수 선언

(2). 주소록에 새로운 주소 정보를 추가하는 함수

  전에는 useEffect 훅이 주소 정보를 감지하고 있다가 주소 정보가 바뀌었다면 useEffect 안에서 주소록에 새로운 주소 정보를 추가했지만 이제는 이 함수가 그러한 역할을 함

  단, 함수이므로 주소 정보를 감지하지는 않음

(3). 주소 정보 추가 컴포넌트로 주소 정보를 추가할 수 있는 함수를 넘김

(4). 주소록 출력 컴포넌트로 주소록을 넘김

 

 

프로젝트 -> src -> chapter04 -> AddressAdd.jsx 파일을 추가하고 아래 코드를 추가하자

import React, {useState} from 'react';

function AddressAdd(props) {
    const [nameVal, setNameVal] = useState();
    const [telVal, setTelVal] = useState();
    const [addressVal, setAddressVal] = useState();
    const appendAddressInfo = props.appendAddressInfo;

    let clickAddBtn = () => {
        let addressInfo = {
            "name": nameVal,
            "tel": telVal,
            "address": addressVal,
            "rdate": new Date().getTime()
        }

        appendAddressInfo(addressInfo);
    }

    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="이름" onChange={(e) => setNameVal(e.target.value)} />
                </div>
                <div className="col-2">
                    <input type="tel" className="form-control" placeholder="연락처"  onChange={(e) => setTelVal(e.target.value)} />
                </div>
                <div className="col-5">
                    <input type="text" className="form-control" placeholder="주소" onChange={(e) => setAddressVal(e.target.value)} />
                </div>
                <div className="col-2 text-center">
                    <button type="button" className="btn btn-primary" onClick={clickAddBtn}>추가</button>
                </div>
            </div>
            <hr />
        </div>
    );
}

export default AddressAdd;

<< 코드 설명 >>

여기는 바뀐 부분이 크지 않음

(1). 부모 컴포넌트가 전달한 주소록 추가 함수를 꺼냄

(2). 추가 버튼 클릭 시 주소록에 새로운 주소 정보 추가

 

 

프로젝트 -> src -> chapter04 -> AddressList.jsx 파일 추가 후 아래 코드 추가

import React from 'react';
import Address from './Address';

function AddressList(props) {
    const addressInfoList = props.addressInfoList;

    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>
                    {
                    addressInfoList.map((addressInfo, index) => {
                        return <Address
                                    key={addressInfo.rdate+"_"+index}
                                    index={index}
                                    addressInfo={addressInfo}
                                />
                    })
                    }
                </tbody>
            </table>
        </div>
    );
}

export default AddressList

<< 코드 설명 >>

역시 바뀐 부분이 크지 않음

(1). 부모 컴포넌트가 전달한 주소록을 꺼냄

(2). 주소록을 출력

  여기서 살짝 달라진게 있다면 주소 정보를 통째로 전달하고 있다는 점

  그러나 잘 알고 있듯 전혀 특별하진 않음

 

 

프로젝트 -> src -> chapter04 -> Address.jsx 파일 추가 후 아래 코드 추가

import React from 'react';

function Address(props) {
    const addressInfo = props.addressInfo;

    return(
        <tr className="row">
            <th className="col-1" scope="row">{props.index+1}</th>
            <td className="col-2">{addressInfo.name}</td>
            <td className="col-2">{addressInfo.tel}</td>
            <td className="col-5 text-left">{addressInfo.address}</td>
            <td className="col-2">
                <div className="btn-group" role="group" aria-label="Basic example">
                    <button type="button" className="btn btn-success">수정</button>
                    <button type="button" className="btn btn-danger">삭제</button>
                </div>
            </td>
        </tr>
    );
}

export default Address;

<< 코드 설명 >>

(1). AddressList 부모 컴포넌트가 전달한 주소 정보를 꺼냄


chapter03의 주소록 프로젝트와 여기(chapter04)의 주소록 프로젝트의 차이점은 useEffect 유무

useEffect 훅을 사용해 변수의 변화를 감지할 수도 있지만 useEffect 훅을 사용하지 않아도 변수의 변화를 감지할 수 있음

chapter03에서도 설명했듯이 컴포넌트가 갖고 있는 변수에 변화가 생기면 리엑트는 컴포넌트 내 변수의 값을 바꾸는게 아닌 바뀐 값을 갖고 있는 새로운 컴포넌트를 만들어 교체하기 때문임

 

여기서 AddressAdd 컴포넌트에서 AddressMng 부모 컴포넌트가 갖고 있는 addressInfoList에 변화를 주는데 이렇게 자식 컴포넌트가 부모 컴포넌트의 변수에 변화를 주는 걸 State 끌어올리기 라고 부름

 

주소록 수정과 삭제도 State 끌어올리기 를 사용할 수 있으니 그 부분은 여러분이 직접 해보자

728x90
LIST

<< 학습 목표 >>

1. 리엑트 라우터(Router) 라이브러리가 필요한 이유를 설명할 수 있다.

2. 리엑트 라우터(Router) 라이브러리를 사용해 SPA를 구현할 수 있다.

3. URL 파라미터를 사용할 수 있다.


리엑트가 SPA ( Single Page Application ) 을 구현할 수 있다고 했는데 지금까지는 페이지 하나에서 모두 처리했음

이번에는 리엑트로 SPA를 구현할 수 있는 라우터(Router) 를 배워보자

 

라우터를 사용하려면 프로젝트에 react-router-dom 라이브러리를 설치해야함

vs code 에서 터미널을 열고 프로젝트로 이동한 후 프로젝트에 react-router-dom 라이브러리를 설치하자

1. 프로젝트로 이동 : cd study-project

2. react-router-dom 라이브러리 설치 : npm install react-router-dom


리엑트 라우터는 브라우저의 URL 경로를 사용하여 특정 컴포넌트를 불러오는(렌더링하는) 라이브러리임

 

라우터를 사용하는 이유는 다음과 같음

1. 브라우저의 URL 경로를 사용하여 컴포넌트를 보여줄 수 있음

2. SPA는 모든 컨텐츠(컴포넌트)를 하나의 페이지에서 보여줌

  이러한 SPA를 구현하려면 브라우저의 URL 경로를 사용하여 컴포넌트를 보여줘야함

  리엑트 라우터는 이러한 SPA를 구현하는 데 필요한 기능을 제공함

3. 리엑트 라우터를 사용하면 중첩된 컴포넌트 간의 라우팅을 처리할 수 있음

4. 리엑트 라우터는 브라우저의 히스토리를 관리할 수 있음

  이를 통해 뒤로가기, 앞으로가기 버튼 등을 사용하여 페이지 이동을 처리할 수 있음

 

리엑트 라우터의 장점은 다음과 같음

1. SPA 구현이 용이함

2. 중첩된 라우팅을 지원함

3. 히스토리 관리가 가능함

4. 동적 라우팅을 지원함

 

리엑트 라우터의 단점은 다음과 같음

1. 학습을 하기 위해 시간이 다소 소요될 수 있음

2. 라우터를 남용하면 프로젝트가 필요 이상으로 복잡해질 수 있음

3. SEO 최적화가 어려움

  SEO란 검색 엔진 최적화인데 검색 사이트에서 검색이 되고 상위에 노출될 수 있도록 하는 작업을 뜻함

  이를 위해서 많은 사이트에서 각 컨텐츠(페이지, 컴포넌트)별로 페이지 내 다양한 키워드를 넣어둠

  그러나 리엑트 라우터는 SPA 이므로 하나의 페이지에서 모든 컨텐츠를 다 보여줘 각 페이지별 다양한 키워드를 넣기 어렵다는 점 등 SEO 최적화가 어렵다는 단점이 있음

 

SPA를 구현하기 위해서는 라우터 라이브러리가 필수이지만 단점도 있으니 단점을 해결할 방안도 찾는것이 좋음


이제 리엑트 라우터를 실습하자

라우터를 실습하기 위해 프로젝트 -> src -> chapter04 폴더 내 아래와 같은 컴포넌트들을 추가할 것

1. Component02.jsx : 브라우저의 URL에 맞는 페이지를 불러올 컴포넌트

2. Home.jsx : 브라우저의 URL이 / 일 경우 보여줄 컴포넌트

3. About.jsx : 브라우저의 URL이 /about 일 경우 보여줄 컴포넌트

4. List.jsx : 브라우저의 URL이 /topics 일 경우 보여줄 컴포넌트

 

<< 1. Component02.jsx >>

import React from 'react';

function Component02() {
    return(
        <div style={{margin: "20px"}}>
            <nav>
                <span>Home</span>&nbsp;&nbsp;&nbsp;&nbsp;
                <span>About</span>&nbsp;&nbsp;&nbsp;&nbsp;
                <span>List</span>
            </nav>

            <div>
                {/* URL에 맞는 컴포넌트를 보여줄 영역 */}
            </div>
        </div>
    );
}

export default Component02;

위 컴포넌트에서 nav 태그가 사이트 메뉴 역할을 함

 

nav 태그 밑에 있는 div 태그가 메뉴에 맞는 컴포넌트를 보여줄 태그임

HTML만 사용했다면 nav 태그 내 span 태그에 a 태그를 넣어야하지만 리엑트 라우터의 경우 Link 컴포넌트를 사용함

<< 코드 설명 >>

(1). Link 컴포넌트를 사용하기 위해서는 import 를 해야함

(2). 링크가 필요한 곳에 a 태그 대신 Link 컴포넌트를 사용함

  Link 태그의 to 속성이 a 태그의 href 속성과 같은 역할을 함

 

 

브라우저 URL에 맞는 컨텐츠를 보여줄 영역에는 Routes 컴포넌트와 Route 컴포넌트를 사용함

<< 코드 설명 >>

(1). Routes, Route 컴포넌트를 사용하기 위해서는 각 컴포넌트를 import 해야함

(2). Route 컴포넌트를 사용해 브라우저 URL에 맞는(path 속성) 컴포넌트를 불러오도록 설정함(element 속성)

  그 후 Route 컴포넌트들을 Routes 컴포넌트로 감싸야함

 

 

Component02 컴포넌트의 마지막으로 Link 컴포넌트들과 Routes 컴포넌트를 BrowserRouter 컴포넌트로 감싸야함

< < 코드 설명 >>

(1). BrowserRouter 컴포넌트를 사용하기 위해서는 import를 해야함

(2). Link 컴포넌트부터 Routes 컴포넌트까지 BrowserRouter 컴포넌트로 감싸야 Link, Routes 컴포넌트가 동작함


이제 브라우저 URL에 따라 페이지에 보여줄 컴포넌트들을 추가하자

컴포넌트는 아래와 같이 간단하게 추가할 것임

프로젝트 -> src -> chapter04 -> Home.jsx

import React from 'react';

function Home() {
    return(
        <div>
            <h1>Home 컴포넌트</h1>
        </div>
    );
}

export default Home;

 

프로젝트 -> src -> chapter04 -> About.jsx

import React from 'react';

function About() {
    return(
        <div>
            <h1>About 컴포넌트</h1>
        </div>
    );
}

export default About;

 

프로젝트 -> src -> chapter04 -> List.jsx

import React from 'react';

function List() {
    return(
        <div>
            <h1>List 컴포넌트</h1>
        </div>
    );
}

export default List;

 

Component02 컴포넌트에 화면에 보여줄 컴포넌트들을 불러오자(1)

 

Component02 컴포넌트를 웹 페이지에 출력해보자

각 메뉴를 클릭하면 URL이 이동하면서 URL에 맞는 각 컴포넌트들이 보임

 

지금 페이지들의 링크 구조를 보면 다음과 같음

 


페이지들의 링크 구조를 다음과 같이 추가하려면 어떻게 해야할까?

즉, 지금은 Component02 컴포넌트에서 링크를 눌러 Home, About, List 컴포넌트를 불러오고 있는 구조임

여기에 List 컴포넌트에 링크를 추가해 List 컴포넌트에서 링크를 눌러 part1, part2 컴포넌트로 이동하는 구조를 추가하고 싶음

 

그럴 때는 우선 List 컴포넌트에 이동할 수 있게 링크를 추가해야함

<< List 컴포넌트 소스 코드 >>

더보기

import React from 'react';
import { Link } from 'react-router-dom';

function List() {
    return(
        <div>
            <h1>List 컴포넌트</h1>

            <ul>
                <li><Link to="/list/part1">Part1</Link></li>
                <li><Link to="/list/part2">Part2</Link></li>
            </ul>
        </div>
    );
}

export default List;

 

그 후 Component02 컴포넌트의 Routes 안에 Route 컴포넌트로 URL에 맞는 컴포넌트를 보여주도록 할 수 있음

<< Component02 컴포넌트 소스 코드 >>

더보기

import React from 'react';
import { Link, Routes, Route, BrowserRouter } from 'react-router-dom';
import Home from './Home';
import About from './About';
import List from './List';
import ListPart1 from './ListPart1';
import ListPart2 from './ListPart2';

function Component02() {
    return(
        <div style={{margin: "20px"}}>
            <BrowserRouter>
            <nav>
                <span><Link to="/">Home</Link></span>&nbsp;&nbsp;&nbsp;&nbsp;
                <span><Link to="/about">About</Link></span>&nbsp;&nbsp;&nbsp;&nbsp;
                <span><Link to="/list">List</Link></span>&nbsp;&nbsp;&nbsp;&nbsp;
            </nav>

            <div>
                <Routes>
                    <Route path="/" element={<Home />} />
                    <Route path="/about" element={<About />} />
                    <Route path="/list" element={<List />} />
                    <Route path="/list/part1" element={<ListPart1 />} />
                    <Route path="/list/part2" element={<ListPart2 />} />
                </Routes>
            </div>
            </BrowserRouter>
        </div>
    );
}

export default Component02;


컴포넌트가 GET 파라미터 값을 전달 받았을 때 컴포넌트에서 전달 받은 GET 파라미터는 어떻게 꺼낼까?

다음과 같이 useLocation 훅을 사용해 꺼낼 수 있음

 

<< List 컴포넌트 >>

import React from 'react';
import { Link, useLocation } from 'react-router-dom';

function List() {
    const location = useLocation();
    const parameters = new URLSearchParams(location.search);
    const value = parameters.get("name");

    return(
        <div>
            <h1>List 컴포넌트</h1>
            { value != null && <p>전달 받은 name 파라미터의 값은 {value} 입니다</p> }
            <ul>
                <li><Link to="/list/part1">Part1</Link></li>
                <li><Link to="/list/part2">Part2</Link></li>
            </ul>
        </div>
    );
}

export default List;

 

<< 코드 설명 >>

(1). useLocation 훅을 사용하기 위한 import

(2). useLocation 훅을 사용해 JS의 location 객체를 리엑트로 가져옴

(3). URLSearchParams 클래스를 사용해 location 객체가 가지고 있는 GET 파라미터 값들을 꺼내기 쉽게 변환함

  변환한 후 parameters 변수에 저장

(4). get 함수를 사용해 parameters 변수에 저장된 파라미터 값을 꺼내 value 변수에 저장

  이때 꺼낼 파라미터의 이름을 인자로 넣음

  위 코드는 GET 파라미터로 name=값 으로 전달했기 때문에 name 파라미터 값을 꺼내는 코드임

(5). 꺼낸 GET 파라미터를 출력함


또한 URL의 경로 중 일부를 파라미터로 사용할 수도 있음

 

Component02 컴포넌트에 URL의 경로 중 일부를 파라미터로 사용할 수 있도록 설정해보자

<< Component02 컴포넌트 소스 코드 >>

import React from 'react';
import { Link, Routes, Route, BrowserRouter } from 'react-router-dom';
import Home from './Home';
import About from './About';
import List from './List';
import ListPart1 from './ListPart1';
import ListPart2 from './ListPart2';
import AboutWho from './AboutWho';

function Component02() {
    return(
        <div style={{margin: "20px"}}>
            <BrowserRouter>
            <nav>
                <span><Link to="/">Home</Link></span>&nbsp;&nbsp;&nbsp;&nbsp;
                <span><Link to="/about">About</Link></span>&nbsp;&nbsp;&nbsp;&nbsp;
                <span><Link to="/about/me">About Me</Link></span>&nbsp;&nbsp;&nbsp;&nbsp;
                <span><Link to="/about/you">About Your</Link></span>&nbsp;&nbsp;&nbsp;&nbsp;
                <span><Link to="/list">List</Link></span>&nbsp;&nbsp;&nbsp;&nbsp;
            </nav>

            <div>
                <Routes>
                    <Route path="/" element={<Home />} />
                    <Route path="/about" element={<About />} />
                    <Route path="/about/:who" element={<AboutWho />} />
                    <Route path="/list" element={<List />} />
                    <Route path="/list/part1" element={<ListPart1 />} />
                    <Route path="/list/part2" element={<ListPart2 />} />
                </Routes>
            </div>
            </BrowserRouter>
        </div>
    );
}

export default Component02;

<< 코드 설명 >>

(1). about URL 다음에 /me 또는 /you 경로를 더 붙인 링크를 추가했음

(2). /about/me, /about/you 를 /list/part1, /list/part2 처럼 처리할 수도 있지만 /about/me, /about/you 는 me, you 를 파라미터로 사용하기 위해 path가 /about/:who 인 Route 컴포넌트를 추가

  :who 가 아니어도 됨 :a, :b 와 같이 아무 문자나 가능하나 위와 같이 의미 있는 문자를 사용하는게 좋음

  /about/me, /about/you 모두 (2)의 Route가 지정한 컴포넌트인 AboutWho 컴포넌트가 보임

 

프로젝트 -> src -> Chapter04 -> AboutWho.jsx 를 추가하고 아래 코드를 추가하자

import React from 'react';
import { useParams } from 'react-router-dom';

function AboutWho() {
    const {who} = useParams();

    return(
        <div>
            <h1>About</h1>
            <h3>{who} 입니다</h3>
        </div>
    );
}

export default AboutWho;

<< 코드 설명 >>

(1). URL 중 일부를 파라미터로 사용하기 위해서는 useParams 훅을 import 해야함

(2). URL 중 일부를 파라미터로 가져오기 위해 useParams 훅을 사용했음

  Component02 컴포넌트 소스 코드 에서 봤던 me 또는 you 가 who 변수에 저장됨

(3). who 변수에 저장한 파라미터를 출력

728x90
LIST

<< 학습 목표 >>

1. 입력 폼에 기본값을 갖도록 설정할 수 있다.

2. 입력 폼이 기본값을 가지면서 변경되도록 설정할 수 있다.


리엑트로 입력 폼(form)을 핸들링 하는 방법은 지금까지 우리가 중간 중간 배운대로만 알아도 됨

가끔 필요한 경우가 있는 것들만 간단하게 알아보자

 

우선 프로젝트 -> src -> chapter04 폴더를 만들자

그 후 chapter04 폴더 내 Component01.jsx 파일을 추가하고 아래 코드를 추가하자

 

<< 기본 값이 들어있는 입력 폼 >>

1. 한 줄 입력

  간단하게 한 줄로 입력할 수 있는 input 태그의 경우 HTML과 동일하게 value 속성을 사용해서 기본값을 가지고 있는 한 줄 입력 폼을 구성할 수 있음

 

2. 여러 줄 입력

  여러 줄로 입력할 수 있는 textarea 태그의 경우 HTML과 다르게 value 속성을 사용해서 기본값을 가지고 있는 여러 줄 입력 폼을 구성할 수 있음

 

한 줄, 여러 줄 입력 시 당연히 JSX를 사용할 수 있음

여기서 주의할 점은 위와 같이 기본값을 갖도록 하면 기본값을 갖긴 하지만 입력을 할 수는 없음

위와 같이 컴포넌트를 수정 한 후 출력해 확인해보자

이를 활용하면 회원 정보 수정 시 아이디는 바꿀 수 없게 만들 수 있음

 

기본값도 가지면서 입력을 허용하려면 useState 훅과 onChange 이벤트 핸들러를 사용해야함

 

3. 체크박스, 라디오버튼

  체크박스와 라디오 버튼의 경우 HTML과 동일하게 checked 속성을 사용해 기본값이 체크되도록 할 수 있음

역시나 체크박스와 라디오 버튼을 위와 같이 설정한다면 체크를 풀 수 없는 상태가 됨

기본값이 체크된 상태로 다른 항목이 체크 되도록 하려면 useState 훅과 onChange 이벤트 핸들러를 사용해야함

또한 조건부 렌더링도 함께 사용해야함

 

체크박스와 라디오 버튼의 경우 다른 항목이 체크 되도록 하는 방식이 다르니 따로 보자

3-1. 체크박스가 기본값을 체크하면서 다른 항목도 체크하도록 만들고 싶을 때

  체크 박스가 기본값을 체크하면서 다른 항목도 체크하도록 만들고 싶을 때는 체크 박스의 각 항목별 상태를 저장할 변수를 선언(1)해야함

체크 박스는 체크했음(ture), 체크안했음(false)으로 핸들링 할 수 있으니 기본값을 체크하기 위해서 기본값의 상태를 저장할 변수에 true를 저장하고 나머지 항목들은 false를 저장하면 됨

체크 박스에서는 checked 속성을 통해 기본값을 체크하도록 핸들링할 수 있음(2)

또한 체크 박스의 체크 상태가 변했을 때 호출할 함수를 이벤트 핸들러로 등록해야함(2)

체크 박스의 체크 상태가 변했을 때 setter 함수를 사용해 체크 상태를 저장(3) 하도록 하면 기본값이 체크 된 상태로 다른 항목들도 체크할 수 있음

 

3-2. 라디오 버튼이 기본값을 체크하면서 다른 항목을 체크하도록 만들고 싶을 때

  라디오 버튼은 항목 중 하나를 선택하는 버튼이므로 기본값 또는 현재 선택한 항목의 값을 저장하기 위해 변수를 하나만 선언함(1)

라디오 버튼 역시 체크박스처럼 checked 속성을 통해 기본값을 체크하도록 핸들링할 수 있음(2)

또한 라디오 버튼의 체크 상태가 변했을 때 호출할 함수를 이벤트 핸들러로 등록해야함(2)

체크박스의 상태가 변했을 때 체크한 항목의 값으로 변경하도록 함(3)

 

4. select

select 의 경우 HTML과 동일하게 value 속성을 사용해서 기본값이 체크되도록 할 수 있음

단, 지금까지 봐온것처럼 위와 같이 한다면 기본값을 바꿀 수 없음

select의 기본 값을 바꾸도록 하려면 useState 훅과 onChange 이벤트 핸들러를 사용해야함

 

각 입력 폼의 기본값 설정 방법과 값을 바꿀 때 설정 방법들이 비슷한듯 다르니 잘 기억해두기

728x90
LIST