52일차 TIL (Lv.1과제 .ts 파일로 리팩토링 / **)
void ?
void는 TypeScript에서 함수의 반환 타입으로 사용되는 특별한 타입
함수가 어떤 값을 반환하지 않을 때 void를 반환 타입으로 명시할 수 있다
예를 들어, 아래와 같이 void를 반환 타입으로 지정하면, 함수가 어떤 값을 반환하지 않을 것을 나타낼 수 있다
function sayHello(): void {
console.log('Hello, World!');
}
void는 반환 값이 없음을 명시하는 역할을 한다
함수가 return 구문을 사용하지 않거나, return 구문이 있더라도 반환값을 명시적으로 지정하지 않을 때 사용
함수형 컴포넌트에서도 void를 반환 타입으로 지정할 수 있다.
예를 들어, 다음과 같이 React.FC와 void를 함께 사용하여 함수형 컴포넌트를 정의할 수 있다.
import React from 'react';
const MyComponent: React.FC = () => {
const handleClick = (): void => {
console.log('Button clicked!');
};
return <button onClick={handleClick}>Click Me</button>;
};
export default MyComponent;
이 경우, MyComponent는 React.FC로 정의되었으며, handleClick 함수는 void를 반환
즉, 해당 컴포넌트는 어떤 값을 반환하지 않으며, 버튼을 클릭할 때 콘솔에 메시지가 출력될 뿐
app. tsx 코드
import React from "react";
import { useState } from "react";
import "./Tab.css";
import Tabs from "./components/Tabs";
import DefaultBtn from "./components/DefaultBtn";
interface Tab {
id: number;
title: string;
detail: string;
isDone: boolean;
}
const App: React.FC = () => {
const [tabs, setTabs] = useState<Tab[]>([
{
id: 1,
title: "React 공부하기",
detail: "React 기초에 대하여",
isDone: false,
},
{
id: 2,
title: "JS 공부하기",
detail: "문제 풀기 & 복습",
isDone: false,
},
{
id: 3,
title: "러닝 40분",
detail: "3:1 비율로 인터벌",
isDone: false,
},
]);
const [title, setTitle] = useState<string>(""); // title 상태의 타입 지정
const [detail, setDetail] = useState<string>(""); // detail 상태의 타입 지정
// 초기값 tabs 이후에 추가되는 tabs을 만들어줄 함수를 선언해준다;
const addHandler = () => {
if (title === "" || detail === "") {
alert("입력란을 채워 주세요.");
return;
}
const newTab: Tab = {
id: tabs.length + 1,
title: title,
detail: detail,
isDone: false,
};
// setTabs((prevTabs) => [...prevTabs, newTab]);
// 기존 할 일 목록에 새로운 항목 추가
setTabs([...tabs, newTab]);
setTitle("");
setDetail("");
};
const deleBtn = (id: number) => {
const newTabs = tabs.filter((tab) => tab.id !== id);
setTabs(newTabs);
};
const toggleBtn = (id: number) => {
const doneTab = tabs.find((tab) => tab.id === id);
if (doneTab) {
doneTab.isDone = !doneTab.isDone;
const newDoneTab = tabs.filter((tab) => tab.id !== id);
setTabs([...newDoneTab, doneTab]);
}
};
// 진행 중인 일과 완료한 일을 구분하여 필터링
const workingOnTab = tabs.filter((tab) => !tab.isDone);
const finallyDoneTab = tabs.filter((tab) => tab.isDone);
return (
<div className="appBody">
<header className="appHeader">
<h1>My ToDoList</h1>
<h1>React</h1>
</header>
<div className="appInput">
<label className="titleLable">제목</label>
<input
autoFocus
value={title}
onChange={(e) => setTitle(e.target.value)}
/>
<label className="detailLable">내용</label>
<input
value={detail}
onChange={(e) => setDetail(e.target.value)}
/>
<button onClick={addHandler}>등록하기</button>
</div>
<h1 style={{ padding: "10px 0 0 20px" }}>Working On 🔥</h1>
<div className="tabBody">
{workingOnTab.map((tab) => (
<Tabs
tab={tab}
key={tab.id}
deleBtn={deleBtn}
toggleBtn={toggleBtn}
/>
))}
</div>
<h1 style={{ padding: "10px 0 0 20px" }}>Finally Done 🎉🎉</h1>
<div className="doneBody">
{finallyDoneTab.map((tab) => (
<Tabs
tab={tab}
key={tab.id}
deleBtn={deleBtn}
toggleBtn={toggleBtn}
/>
))}
</div>
</div>
);
};
export default App;
Tab.tsx 코드
import React from "react";
import DefaultBtn from "./DefaultBtn";
interface Tab {
id: number;
title: string;
detail: string;
isDone: boolean;
}
interface TabsProps {
tab: Tab;
deleBtn: (id: number) => void;
toggleBtn: (id: number) => void;
}
const Tabs: React.FC<TabsProps> = ({ tab, deleBtn, toggleBtn }) => {
const { id, title, detail, isDone } = tab;
return (
<div className={`userTab ${isDone ? "complete" : ""}`}>
<div className="tabTitle">{title}</div>
<div className="tabDetail">{detail}</div>
<div className="btns">
<button className="redBtn" onClick={() => deleBtn(id)}>
삭제
</button>
<button className="blueBtn" onClick={() => toggleBtn(id)}>
{isDone ? "취소" : "완료"}
</button>
</div>
</div>
);
};
export default Tabs;
DefaultBtn은 오류가 있어서 닫아놨다.
일반 button으로 치환해서 수정해놓았다.