useNavigate를 사용한 페이지 이동(4)

호박이와 칼림바·2023년 10월 26일
post-thumbnail

📗목차

현재 로그인 버튼의 기능은 id와 password를 둘 다 입력했을 때 버튼 색상이 활성화 되는 것이다.
이 기능에 더해 버튼을 클릭했을 때의 페이지 전환을 해줘야 된다.
페이지 전환을 위해서 useNavigate를 사용할 줄 알아야 한다.

react-router-dom은 이전에 설치하였으니 import 부분에 useNavigate만 추가해보자.
그런 다음 useNavigate() 함수를 호출하여 navigate라는 함수를 생성하면 된다.

LoginBox.js

import React, { useState, useEffect } from 'react';
import { Routes, Route, Link, useNavigate } from 'react-router-dom';
import Hint from './Hint';
import '../style/LoginBox.css';

const LoginBox = () => {
  	(...) // 생략 
    const navigate = useNavigate();

    return (
        <>
            <section className="login-form">
                (...) // 생략  
               
                <button 
                    id="btn-login"   
                    type="submit"                         // 노란색 : 회색
                    style={{ backgroundColor: isActive ? "#d8db31" : "rgba(209, 206, 206, 0.733)" }} // style 동적으로 변경
                >
                    LOGIN
                </button>
                <div id="hint">
                    <Link to="/hint">Click to get a hint</Link>
                </div>
            </section>
            <Routes>
                <Route path="/hint" element={<Hint />}></Route>
            </Routes>
        </>
    )
};

export default LoginBox;

그럼 이제 버튼을 클릭했을 때의 이벤트를 만들어 보겠다.

1. 버튼 onClick 이벤트

먼저 Album 컴포넌트를 생성할 것이다.

Album 컴포넌트 생성

import React from 'react';

const Album = () => {
	return
};

export default Album;

그 다음 Album 컴포넌트로 이동할 수 있는 Route 경로를 하나 더 추가해준다.

LoginBox 컴포넌트의 Route

<Routes>
    <Route path="/album" element={<Album />}></Route>
    <Route path="/hint" element={<Hint />}></Route>
</Routes>

그런 다음 button을 클릭했을 때 나타나는 이벤트 함수를 작성해준다.

const access = () => {
    if(id === 'oeanb' && password === '1234') navigate('/album')
    else if(id === '') alert('아이디를 입력해주세요.');
    else if(password === '') alert('비밀번호를 입력해주세요.');
    else alert('아이디 또는 비밀번호가 맞지 않습니다. 다시 입력해주세요.');
};

id와 password를 각각 'oeanb', '1234'을 입력 했다면, '/album'으로 페이지 주소를 이동하게 하였다.
id와 password 둘 중 하나라도 비어 있거나 틀릴 경우 알림 메시지를 띄었다.


위에서 작성한 access 함수를 button 클릭 이벤트에 적용해보자.

LoginBox 컴포넌트의 button 부분

<button 
	id="btn-login"   
    type="submit"           
    onClick={access}                       // 노란색 : 회색
    style={{ backgroundColor: isActive ? "#d8db31" : "rgba(209, 206, 206, 0.733)" }} // style 동적으로 변경

    LOGIN
</button>

이제 버튼을 마우스로 클릭했을 때는 정상 작동한다.

2. onKeyDown 이벤트

로그인 버튼을 클릭하면 페이지 이동이 되는 것은 완성했다.
하지만, 보통 아이디와 비밀번호를 입력한 후에 버튼을 클릭하며 로그인 하지 않는다.
우린 보통 Enter 키를 누른다.

그래서 onKeyDown 이벤트도 등록하려고 한다.

onKeyDown 이벤트

const handleKeyDown = e => {
    e.key === "Enter" && access();
}, [id, password]);

key가 Enter일 경우 access() 함수를 실행하도록 하였다.
access() 함수를 다시 보자.

const access = () => {
    if(id === 'oeanb' && password === '1234') navigate('/album')
    else if(id === '') alert('아이디를 입력해주세요.');
    else if(password === '') alert('비밀번호를 입력해주세요.');
    else alert('아이디 또는 비밀번호가 맞지 않습니다. 다시 입력해주세요.');
};

그럼 이제 이 onKeyDown 이벤트는 어디에 적용해야 될까?
답은 form 태그에 적용해야 된다.

Enter 키를 누르고 나면 id와 password를 입력한 데이터가 제출된다.
access() 함수에서 제출된 데이터를 확인하고 로그인 성공 여부를 알려준다.

3. useCallback을 사용하여 렌더링 성능 높이기

Hooks 게시글
Hook을 사용하면서 컴포넌트가 렌더링 될때마다 함수를 생성하게 된다.
컴포넌트의 렌더링이 자주 발생하거나 렌더링해야 할 컴포넌트의 개수가 많아지면 성능이 나빠지게 된다. 그래서 필요할 때만 생성할 수 있게 해주는 useCallback Hook을 사용해보겠다.

전체 코드에서 확인해보자.

LoginBox 전체 코드

import React, { useState, useEffect, useCallback } from 'react';
import { Routes, Route, Link, useNavigate } from 'react-router-dom';
import Hint from './Hint';
import Album from './Album';
import '../style/LoginBox.css';

const LoginBox = () => {
    const [ isActive, setIsActive ] = useState(false);
    const [ form, setForm ] = useState({
        id: '',
        password: ''
    });
    const { id, password } = form;
    const navigate = useNavigate();

    useEffect(() => {
        // id와 password 값의 유무에 따른 활성화 상태 
        id !== '' && password !== '' ? setIsActive(true) : setIsActive(false)    
    }, [id, password]);

    const handleInputChange = useCallback(e => {
        setForm(prevForm => ({
            ...prevForm,
            [e.target.name]: e.target.value
        }));
    }, []);
    const handleKeyDown = useCallback(e => {
        e.key === "Enter" && access();
    }, [id, password]);

    const access = useCallback(e => {
        if(id === '이상미' && password === '981223') navigate('/album')
        else if(id === '') alert('아이디를 입력해주세요.');
        else if(password === '') alert('비밀번호를 입력해주세요.');
        else alert('아이디 또는 비밀번호가 맞지 않습니다. 다시 입력해주세요.');
    }, [id, password, navigate]);
  
    return (
        <>
            <section className="login-form">
                <h1>추억을 로그인</h1>
                <form 
                    onKeyDown={handleKeyDown}
                >    
                    <div className="int-area">
                        <input 
                            type="text" 
                            name="id" 
                            value={id}
                            onChange={handleInputChange}
                            id="name-input" 
                            required 
                        />
                        <label>Username</label>
                    </div>
                    <div className="int-area">
                        <input 
                            type="password" 
                            name="password" 
                            value={password}
                            onChange={handleInputChange}
                            id="password-input" 
                            required 
                        />
                        <label>Password</label>
                    </div>
                </form>    
                
                <button 
                    id="btn-login"   
                    type="submit"           
                    onClick={access}                       // 노란색 : 회색
                    style={{ backgroundColor: isActive ? "#d8db31" : "rgba(209, 206, 206, 0.733)" }} // style 동적으로 변경
                >
                    LOGIN
                </button>
                <div id="hint">
                    <Link to="/hint">Click to get a hint</Link>
                </div>
            </section>
            <Routes>
                <Route path="/album" element={<Album />}></Route>
                <Route path="/hint" element={<Hint />}></Route>
            </Routes>
        </>
    )
};

export default LoginBox;

다음에는 Hint 컴포넌드 컨텐츠를 구현해보겠다.

profile
프론트엔드 개발자입니다.

0개의 댓글