로그아웃 기능을 구현하던중 문제를 발견했다. 문제가 뭐냐면 나는 Dashboard안에 컴포넌트를 정의했다. 하지만 이 컴포넌트는 Dashboard 밖에서 쓰이는데, Dashboard안에 정의된 handleLogout이라는 컴포넌트의 스코프는 Dashboard컴포넌트 이므로 이 밖에서 쓰려고 하면 undefined에러를 발생 시킬것이다. 그렇다면 이때, 어떻게 해야 할까?
먼저, 아래 코드부터 살펴보자.
import React, { useState } from 'react';
import { toast, ToastContainer } from 'react-toastify';
import 'react-toastify/dist/ReactToastify.css';
import { Button } from 'react-bootstrap';
import { useNavigate } from 'react-router-dom';
import 'bootstrap/dist/css/bootstrap.min.css';
import '@fortawesome/fontawesome-free/css/all.min.css';
const Sidebar = ({ isOpen, toggleSidebar }) => (
<div style={{
width: isOpen ? '250px' : '80px',
transition: 'width 0.3s',
backgroundColor: '#800000',
height: '100vh',
position: 'fixed',
color: 'white',
padding: '1rem',
overflow: 'hidden',
zIndex: 1000
}}>
<div onClick={toggleSidebar} style={{ cursor: 'pointer', marginBottom: '2rem', display: 'block', visibility: 'visible', position: 'relative' }}>
<i className="fas fa-bars" style={{ fontSize: '1.5rem', color: 'white' }}></i>
</div>
{isOpen && (
<>
<div style={{ textAlign: 'center' }}>
<img src="profile_picture_url" alt="Profile" style={{ borderRadius: '50%', width: '100px', height: '100px' }} />
<h3>Jihoo Jeong</h3>
<p>Group 6</p>
</div>
<div style={{ marginTop: '2rem', textAlign: 'center' }}>
<Button variant="light" style={{ width: '100%', marginBottom: '1rem', backgroundColor: '#6a5acd', color: 'white' }}>Dashboard</Button>
<Button variant="light" style={{ width: '100%', marginBottom: '1rem', backgroundColor: '#6a5acd', color: 'white' }}>Teams</Button>
<Button variant="light" style={{ width: '100%', marginBottom: '1rem', backgroundColor: '#6a5acd', color: 'white' }}>Settings</Button>
</div>
<div style={{ marginTop: 'auto', textAlign: 'center' }}>
<Button variant="secondary" style={{ backgroundColor: '#6a5acd', width: '100%' }}>Create Teams</Button>
<Button onClick = {handleLogout} variant="danger" style={{ marginTop: '1rem', width: '100%' }}>Sign Out</Button>
</div>
</>
)}
</div>
);
const Card = ({ children, header }) => (
<div className="card" style={{ borderRadius: '1rem', backgroundColor: '#ffe4e1', border: '1px solid #ccc', margin: '1rem 0' }}>
<div className="card-header" style={{ backgroundColor: '#f08080', color: 'white', borderRadius: '1rem 1rem 0 0', padding: '1rem' }}>
<h3 className="mb-0">{header}</h3>
</div>
<div className="card-body p-5 text-center">
{children}
</div>
</div>
);
const Container = ({ children }) => (
<div style={{ display: 'flex' }}>
{children}
</div>
);
const MainContent = ({ children, isSidebarOpen }) => (
<div style={{
marginLeft: isSidebarOpen ? '250px' : '80px',
padding: '2rem',
width: '100%',
transition: 'margin-left 0.3s'
}}>
{children}
</div>
);
const Dashboard = () => {
const [isSidebarOpen, setSidebarOpen] = useState(false);
const navigate = useNavigate();
const toggleSidebar = () => {
console.log("Sidebar toggled");
setSidebarOpen(!isSidebarOpen);
};
const handleGiveFeedback = (event) => {
event.preventDefault();
navigate('/Givefeedback');
};
const handleLogout = () => {
const casLogoutUrl = 'https://login.vt.edu/profile/cas/logout';
window.location.href = casLogoutUrl;
}
return (
<div>
<ToastContainer />
<Container>
<Sidebar isOpen={isSidebarOpen} toggleSidebar={toggleSidebar} />
<MainContent isSidebarOpen={isSidebarOpen}>
<h1>Dashboard</h1>
<Card header="Student Group 1">
<p>Jaison Dasika, Kristian Braun, Jihoo Jeong, Somin Yun</p>
<Button onClick={handleGiveFeedback} variant="primary">Give Feedback</Button>
</Card>
<Card header="Student Group 2" />
<Card header="Student Group 3" />
<Card header="Student Group 4" />
</MainContent>
</Container>
</div>
);
};
export default Dashboard;
- 보면 Dashboard안에 handleLogout이 정의되어있다. 이렇게 되면 Dashboard 컴포넌트 밖에서는 단순 호출을 할 수 없다. 이럴때, 내가 사용하고 싶은곳에 프로퍼티로 넘겨줄 수 있다.
- 내 애플리케이션은 'Sign out' 버튼이 Sidebar 컴포넌트 안에 정의되어 있으므로(여기서 사용할것이므로), Sidebar 컴포넌트안에 프로퍼티로 넘겨준다. 넘겨주는 방식은 아래와 같다.
const Sidebar = ({ isOpen, toggleSidebar, handleLogout }) => (
<div style={{
width: isOpen ? '250px' : '80px',
transition: 'width 0.3s',
backgroundColor: '#800000',
height: '100vh',
position: 'fixed',
color: 'white',
padding: '1rem',
overflow: 'hidden',
zIndex: 1000
}}>
{} 여기 안에 프로퍼티로 넘겨줄 함수, 인자들을 넘겨주면 이제 Sidebar안에서도 Dashboard안에 정의되어있는 컴포넌트들을 호출 할 수 있다.
그런데, 이렇게 코드를 수정하다가 의문이 들었다. "아니 그렇다면, 그냥 Dashboard가 아니라 Dashboard 밖에 global 함수로 선언하면 더 편할텐데?"
※컴포넌트 내부에서 함수 정의
컴포넌트 내부에서 함수를 정의하면 해당 함수는 컴포넌트의 상태(state)와 props에 접근할 수 있다. 이는 함수가 컴포넌트의 동작에 직접적으로 연관된 경우 유용하다.
장점:
- 컴포넌트의 상태와 props에 접근 가능.
- 함수가 해당 컴포넌트의 라이프사이클과 연관될 수 있음.
단점:
- 함수가 컴포넌트 내부에 정의되어 있을 때마다 새로 생성됨. 이로 인해 메모리 사용량이 증가할 수 있음.
- 컴포넌트가 커질수록 복잡성이 증가할 수 있음.
※컴포넌트 외부에서 함수 정의
컴포넌트 외부에서 함수를 정의하면 해당 함수는 독립적으로 동작하며, 특정 컴포넌트에 종속되지 않는다. 이는 함수가 다른 컴포넌트에서도 재사용되거나, 특정 컴포넌트의 상태나 props에 의존하지 않는 경우 유용하다.
장점:
- 재사용성이 높아짐. 여러 컴포넌트에서 동일한 함수를 사용할 수 있음.
- 컴포넌트의 복잡성을 줄일 수 있음.
단점:
- 함수가 컴포넌트의 상태나 props에 접근할 수 없음. 이로 인해 필요한 데이터는 모두 함수 호출 시 전달해야 함.
- 컴포넌트와 함수 간의 결합도가 낮아짐. 이로 인해 특정 상황에서는 불편할 수 있음.
요약
- 내부 정의: 상태와 props에 직접 접근할 수 있으며, 컴포넌트의 라이프사이클과 밀접하게 연관된 경우 유리하다.
- 외부 정의: 재사용성과 코드의 간결성을 높일 수 있으며, 컴포넌트에 종속되지 않는 함수에 적합하다.
'Frontend' 카테고리의 다른 글
[Javascript] DOM이란 무엇일까? + 화살표 함수 (1) | 2024.02.06 |
---|---|
[Javascript]자바스크립트의 함수, 오브젝트, 프로토타입 (1) | 2024.01.29 |
[JavaScript] 자바스크립트의 변수 선언 (0) | 2024.01.28 |
[Bootstrap] 부트스트랩이란 무엇인가? (0) | 2024.01.28 |
[HTML] HTML의 다른 여러가지 태그들 (0) | 2024.01.28 |