[패스트캠퍼스 수강 후기] 프론트엔드 인강 100% 환급 챌린지 22회차 미션 - 30강 React useRef로 특정 DOM 선택하기, 배열 렌더링하기

2 minute read

useRef

특정 DOM에 접근하기 위해서는 ref혹은 함수형 useRef를 사용한다.
아까 만들었던 InputSample에서 몇가지만 더 추가해보자.

import React, { useState, useRef } from 'react'; //1. useRef선언

function InputSample(){
    const [inputs, setInputs] = useState({
        name: '',
        nickname: '',
    }) 
    const nameInput = useRef(); //2. useRef객체를 만듬.
    const { name, nickname } = inputs; 
    const onChange = (e) => {
        const { name, value } = e.target;
        setInputs({
            ...inputs,
            [name]: value, 
        });
    }
    const clearText = () => {
        setInputs({
            name:'',
            nickname:'',
        });
        nameInput.current.focus(); //3. 클리어하는 함수내에서 포커스 연결
    }
    return(
        <div>
            <input 
                placeholder="이름" 
                name="name" 
                onChange={onChange} 
                value={name} 
                ref={nameInput} //4. 사용할 DOM에 useRef변수 꽂기
            />
            <input 
                placeholder="닉네임" 
                name="nickname" 
                onChange={onChange} 
                value={nickname} 
            />
            <button onClick={clearText}>초기화</button>
            <div>
                <b>: </b>
                {name} ({nickname})
            </div>
        </div>
    )
}

export default InputSample;

위와 같이 useRef를 상단에 선언하고 필요한 곳에서 사용해주면 된다.
(근데 궁금한 점은 useRef를 여러곳에서 사용하고 싶으면 어떻게 하지? ㅎㅎ 나중에 알게되면 여기에 다시 포스팅을 이어서 작성하겠다.)

배열 렌더링하기

먼저 UserList.js라는 컴포넌트를 새로 만들어줘 보자.

UserList.js

import React from 'react';

function UserList(){
    const users = [
        {
            id: 1,
            username: 'bmyu',
            email: 'bomee88@naver.com'
        },
        {
            id: 2,
            username: 'tester',
            email: 'tester@example.com'
        },
        {
            id: 3,
            username: 'sample',
            email: 'sample@example.com'
        }
    ];
    
    return(
        <div>
            <div>
                <b>{users[0].username}<span>({users[0].email})</span></b>
            </div>
            <div>
                <b>{users[1].username}<span>({users[1].email})</span></b>
            </div>
            <div>
                <b>{users[2].username}<span>({users[2].email})</span></b>
            </div>
        </div>
    )
}

export default UserList;

이렇게 만들어주고 App.js에서 UserList를 불러와서 화면에 띄워보자.
아래와 같은 화면이 나올 것이다. 이미지 그런데 코드상 같은 div를 여러번 써주는게 내키지 않는다. 그럴경우엔 아래와 같이 User이라는 함수를 하나 더 만들어서 효율적으로 관리할 수 있다.

UserList.js

import React from 'react';

function User({ user }){
    return(
        <div>
            <b>{user.username}<span>({user.email})</span></b>
        </div>
    )
}

function UserList(){
    const users = [
        {
            id: 1,
            username: 'bmyu',
            email: 'bomee88@naver.com'
        },
        {
            id: 2,
            username: 'tester',
            email: 'tester@example.com'
        },
        {
            id: 3,
            username: 'sample',
            email: 'sample@example.com'
        }
    ];
    
    return(
        <div>
            <User user={users[0]}/>
            <User user={users[1]}/>
            <User user={users[2]}/>
        </div>
    )
}

export default UserList;

그런데 만약에 배열의 내용이 고정적이지 않고 늘어나거나 줄어든다면? 그럴땐 js의 map을 사용할 수 있다. map은 이전에 배웠듯이 배열안의 모든 내용에 변형을 주고 싶을 때 각 원소들에 대해 접근하고 새로운 배열을 만들어주는 함수였다.
그래서 우리가 map이라는 함수를 사용해서 객체배열형태로 있는 배열을 컴포넌트 엘리먼트 배열 형태로 변환해주면 된다.

UserList.js

import React from 'react';

function User({ user }){
    return(
        <div>
            <b>{user.username}<span>({user.email})</span></b>
        </div>
    )
}

function UserList(){
    const users = [
        {
            id: 1,
            username: 'bmyu',
            email: 'bomee88@naver.com'
        },
        {
            id: 2,
            username: 'tester',
            email: 'tester@example.com'
        },
        {
            id: 3,
            username: 'sample',
            email: 'sample@example.com'
        }
    ];
    
    return(
        <div>
            {
                users.map(
                    user => (<User user={user} key={user.id}/>) // 객체마다 가지고 있는 고유값을 설정해주어야 . key
                )
            }
        </div>
    )
}

export default UserList;

여기서 중요하게 봐야 할 부분은 map의 key부분이다. key가 없이 리액트를 돌리면 경고가 뜬다. 각 객체마다 고유한 값을 설정해주어야 한다는 경고 문구이다. 지금은 우리가 배열에서 id로 고유한 값을 주었으니 user.id로 고유값을 불러오면 되지만 만약에 고유값이 없는 배열이라면 아래와 같이 임시방편으로 map의 index를 사용할 수도 있다. 하지만 경고문구만 사라지는 것이지 성능상 좋아지는 건 아니다.

    return(
        <div>
            {
                users.map(
                    (user, index) => (<User user={user} key={index}/>) //임시방편으로 index를 쓸수는 있으나 권고하지는 않음
                )
            }
        </div>
    )

그렇다면 key는 무슨역할을 하는 것일까? 배열렌더링 배열렌더링 위의 그림과 같이 key가 없으면 만약에 배열에서 a를 지웠을 때, 배열의 순서대로 a영역을 지우고 기존 a를 b로 치환하고 기존의 b를 c로 치환하고.. 이렇게 업데이트를 한다. 굉장히 비효율적이다.
반면 key를 입력해준 경우에는 해당 배열만 지워버리고 나머지는 그대로 둔다.
그래서 key가 있어야 효율적으로 렌더링을 할 수 있는 것이다. key가 없을 경우엔 index를 넣어줄 순 있지만 위의 키가 없는 사례처럼 매우 비효율적으로 업데이트 될 수 있다는 것을 잘 알아두도록 하자.

오늘은 여기까지..
시청 영상 30강 11~12까지 수강인증이미지

프론트엔드 개발 올인원 패키지 with React Online. 👉 https://bit.ly/31Cf1hp

Comments