Comments.jsx

handleReplyCountBtn 함수 추가const handleReplyCountBtn = (e) => {
};
onClick 이벤트 추가{ item.replyCount !== 0 && item.num === item.groupNum &&
<button onClick={handleReplyCountBtn} className="dropdown-btn btn btn-outline-secondary btn-sm position-absolute"
style={{bottom:"16px", right:"16px"}}>
<i className="bi bi-caret-down"></i>
답글 {item.replyCount} 개
</button>
}
handleReplyCountBtn 함수 안에 코드 추가// click 이벤트가 발생한 버튼의 참조값
const item = e.target;
//click 이벤트가 발생한 그 버튼의 자손요소 중에서 caret up 또는 caret down 요소를 찾는다
const caret = item.querySelector(".bi-caret-up, .bi-caret-down");
// caret 모양을 위 아래로 토글 시킨다
caret.classList.toggle("bi-caret-down");
caret.classList.toggle("bi-caret-up");
// 1. 버튼(item)의 두 단계 부모 요소로 이동
const grandParent = item.parentElement.parentElement;
// 2. 두단계 부모요소의 바로 다음 형제 요소의 참조값을 얻어낸다
let next = grandParent.nextElementSibling;
// 3. 반복문 돌면서 (다음 형제 요소가 있는 동안에 반복문 돌기)
while (next) {
//만일 re-re 클래스가 존재한다면
if (next.classList.contains("re-re")) {
// d-none 클래스를 토글시켜서 보였다 숨겼다를 반복 시킨다
next.classList.toggle("d-none");
}else{//존재하지 않으면
//반복문 탈출
break;
}
//다음 형제 요소의 참조값 얻어내기
next = next.nextElementSibling;
}
react 폴더 안에서 cmd 실행
react-typescript 생성
npm create vite react-typescript
React 선택

TypeScript 선택

react-typescript 폴더로 이동
cd react-typescript
npm install
react-typescript 로 폴더 workspace
npm run dev

rules: {
'no-unused-vars': ['warn', { varsIgnorePattern: '^[A-Z_]' }],
},
function App() {
return <>
<div>
<h1>Type Script 를 사용해 보자</h1>
</div>
</>
}
let 변수명 : typeconst 변수명 : typeint age = 10;
let age : number = 10;
in java ➜ String name = "kimgura"
let name : string = "kimgura";
in java ➜ boolean isMan = true;
let isMan : boolean = true;
infer) 해서 type 을 결정한다let num1 = 10; // num1 은 number type 이다
let yourName = "park"; // yourName 은 string type 이다


useState 함수 추가const [msg, setMsg] = useState("hi");
<button>{msg}</button>

onClick 이벤트 추가<button onClick={() => setMsg("clicked")}>{msg}</button>

useState 함수 추가useState() 를 사용할 때 type 을 명시할 수 있다const [data, setData] = useState<string>();

useState 함수 추가const [num, setNum] = useState<number>();
const nums : number[] = [10, 20, 30];
const names: string[] = ["kim", "lee", "park"];
useState 함수 추가const [friends, setFriends] = useState<string[]>(names);
let m1 = {num:1, name:"유재석", isMan:true};

m1 = {num:2, name:"박명수", isMan:false};
m1 = {myNum:3, myName:"정준하"};
let m2 : {num:number; name:string; isMan:boolean} = m1;
Member 객체 추가type Member = {
num : number;
name : string;
isMan : boolean;
};
let m3 : Member = {
num : 3,
name : "정준하",
isMan : true
};
const members : Member[] = [m1, m2, m3];
function App2() {
return <>
</>
}
() => void 타입으로 추론된다let f1 = () => {};

let f2 : () => void = () => {};
(msg:string) => void 타입으로 추론된다let f3 = (msg:string) => {};

(msg:string) => number 타입으로 추론된다let f4 = (msg:string) => {
return msg.length;
};

➜ 해당 f4 함수는 JAVA 에서 이렇게 해석된다
public int f4(String msg){
return msg.lenght();
}

➜ 에러 발생
const result:number = f4("hello");
type Add = (a:number, b:number) => number;
const getSum:Add = (num1:number, num2:number) => {
return num1 + num2;
};
function App3() {
return <>
</>
}
export type MemberDto = {
num : number;
name : string;
addr : string;
};
export type BoardDto = {
num : number;
writer : string;
title : string;
};
const m1:MemberDto = {num:1, name:"유재석", addr:"압구정"};
const b1:BoardDto = {num:1, writer:"성해나", title:"혼모노"};
null 과 undefined 을 허용하지 않는다const num1:number = null;
const myName:string = undefined;
null 또는 undefined 로 넣으려면 | null 또는 | undefined 를const num2:number|null = null;
const myName2:string|undefined = undefined;
useState 함수 추가const [state, setState] = useState<MemberDto>();

⚠️ 만일 state 초기값을 넣어주지 않는다면 undefined 로 추론된다

useState 에 초기값 전달const [state, setState] = useState<MemberDto>({
num : 0,
name : "",
addr : ""
});
function App4() {
return <>
</>
}
JSX.Element 타입으로 추론된다import type { JSX } from "react";
const p1 = <p>p1 입니다</p>;
const p2:JSX.Element = <p>p2 입니다</p>;
JSX.Element[] 타입으로 추론된다const list = [
<li>하나</li>,
<li>두울</li>,
<li>세엣</li>
];
const list2:JSX.Element[] = [
<li>하나</li>,
<li>두울</li>,
<li>세엣</li>
];
JSX.Element[] 는 Array<JSX:Element> type 의 축약형const list3:Array<JSX.Element> = [
<li>하나</li>,
<li>두울</li>,
<li>세엣</li>
];
handleChange 함수 추가const handleChange = (e) => {
};
onChange 이벤트 추가<input onChange={handleChange} type="text" />
handleChange 함수에 ChangeEvent<HTMLInputElement> 추가change 이벤트가 일어났을 때 전달되는event 객체의 type 은 ChangeEvent<HTMLInputElement> 이다const handleChange = (e:ChangeEvent<HTMLInputElement>) => {
const value = e.target.value;
};
<select>
<option value="one">one</option>
<option value="two">two</option>
</select>
handelSelectChange 함수 추가 및 ChangeEvent<HTMLSelectElement> 사용const handelSelectChange = (e:ChangeEvent<HTMLSelectElement>) => {
const value = e.target.value;
}
onChange 이벤트 추가<select onChange={handelSelectChange}>
<option value="one">one</option>
<option value="two">two</option>
</select>
function App5() {
return (
<div>
</div>
);
}
let name:string|null = null;
type MyData = {
id : number,
title : string|null
};
useData 함수 추가const useData = (data:MyData) => {
};
! : null 이 아닌게 확실해 그러니깐 참조하라는 뜻let result = name!.length;
useData 함수 안에 문자열의 길이를 콘솔로 출력const useData = (data:MyData) => {
console.log(data.title!.length);
};
any 타입을 사용한 a 코드 추가any 타입은 java 의 Object type 과 유사하게 어떤 type 이던지 담을 수 있다let a:any = 10;
a = "kim";
a = () => {};;
function App6() {
return <>
</>
}
Product 타입 선언type Product = {
id : number,
name : string,
price : number
};
useState 함수 추가const [seq, setSeq] = useState<number>(1);

useState 함수 추가const [list, setList] = useState<Array<Product>>([]);

<div className="container">
<h1>상품 목록</h1>
<table>
<thead>
<tr>
<th>아이디</th>
<th>상품명</th>
<th>가격</th>
</tr>
</thead>
<tbody>
{list.map(item =>
<tr key={item.id}>
<td>{item.id}</td>
<td>{item.name}</td>
<td>{item.price}</td>
</tr>
)}
</tbody>
</table>
</div>
<input type="text" placeholder="상품명..."/>
<input type="text" placeholder="가격..."/>
useRef 함수 추가const inputName = useRef(null);
const inputPrice = useRef(null);
ref 속성 추가<input ref={inputName} type="text" placeholder="상품명..."/>
<input ref={inputPrice} type="text" placeholder="가격..."/>
handleClick 함수 추가const handleClick = () => {
};
onClick 이벤트 추가<button onClick={handleClick}>추가</button>
const inputName = useRef<HTMLInputElement>(null);
const inputPrice = useRef<HTMLInputElement>(null);
handleClick 함수 안에 입력한 상품명 읽어오는 코드 추가const name = inputName.current!.value;
handleClick 함수 안에 입력한 가격 읽어오는 코드 추가const price = Number(inputPrice.current!.value);
handleClick 함수 안에 추가할 상품 코드 추가const p1:Product = {
id:seq,
name:name,
price:price
};
handleClick 함수 안에 상품 목록 상태 변경하는 코드 추가setList([...list, p1]);
handleClick 함수 안에 시퀀스 증가 시키는 코드 추가setSeq(seq+1);

function App7() {
return <>
</>
}
const json = `
{"num":1, "name":"유재석", "addr":"압구정"}
`;
const obj = JSON.parse(json);
import type { MemberDto } from './types/type';
const dto1 = obj as MemberDto;
<p>번호 : <strong>{dto1.num}</strong></p>
<p>이름 : <strong>{dto1.name}</strong></p>
<p>주소 : <strong>{dto1.addr}</strong></p>

axios 설치
npm install axios
bootstrap 설치
npm install bootstrap
react-bootstrap 설치
npm install react-bootstrap
Eclipes 는 spring09 로 서버 실행
server: {
proxy: {
'/api': { // 프록시할 경로
target: 'http://localhost:9000', // 백엔드 서버 주소
changeOrigin: true,
secure: false,
rewrite: (path) => path.replace(/^\/api/, ''), // '/api' 제거
},
'/upload':{ // upload 된 이미지를 로딩하기 위한 프록시
target: 'http://localhost:9000',
changeOrigin: true
}
},
},
function Client() {
return <>
</>
}
<div className="container">
<h1>고객 목록</h1>
</div>
useEffect 함수 추가useEffect(() => {
axios.get("/api/v1/clients")
.then(res => {
console.log(res.data);
})
.catch(err => {
console.log(err);
})
}, []);

ClientDto 타입 설정readonly : 읽기 전용으로 수정 불가| null : null 도 가능한 typeexport type ClientDto = {
readonly num : number;
userName : string;
updatedAt : string;
createdAt : string;
birthday : string|null;
formattedBirthday : string|null;
};
ClientDto 타입을 사용하는 목록 관련 useState 함수 추가const [list, setList] = useState<ClientDto[]>([]);
then 문 안에 setList 코드 사용res.data 만 사용하면 any 타입으로 타입을 명확히 알 수가 없다setList(res.data as ClientDto[]);
<table>
<thead>
<tr>
<th>번호</th>
<th>이름</th>
<th>생일</th>
<th>등록일</th>
</tr>
</thead>
<tbody>
{list.map(item =>
<tr key={item.num}>
<td>{item.num}</td>
<td>{item.userName}</td>
<td>{item.formattedBirthday}</td>
<td>{item.createdAt}</td>
</tr>
)}
</tbody>
</table>

useEffect 안에 코드를 주석 처리하고 다시 axios 코드 추가axios.get<ClientDto[]>("/api/v1/clients")
.then(res => {
setList(res.data);
})
.catch(err => console.log(err));

➜ 기존의 코드와 결과는 동일하다
이름 : <input type="text"/><br/>
생일 : <input type="date"/><br/>
<button>추가</button>
ClientDto 타입에 값이 없을 수도 있는 데이터는 ? 를 붙여주기? = optional : 있거나 없거나 상관이 없다export type ClientDto = {
readonly num? : number; // readonly 는 읽기 전용(수정 불가)
userName : string;
updatedAt? : string;
createdAt? : string;
birthday : string|null; // null 도 가능한 type
formattedBirthday? : string|null;
};
useState 함수 추가const [dto, setDto] = useState<ClientDto>({
userName:"",
birthday:""
});
name 속성 부여이름 : <input type="text" name="userName"/><br/>
생일 : <input type="date" name="birthday"/><br/>
handleChange 함수 추가const handleChange = (e:ChangeEvent<HTMLInputElement>) => {
};
onChange 이벤트 추가이름 : <input onChange={handleChange} type="text" name="userName"/><br/>
생일 : <input onChange={handleChange} type="date" name="birthday"/><br/>
handleChange 함수 안에 setDto 사용setDto({
...dto,
[e.target.name] : e.target.value
});
handleClick 함수 추가const handleClick = () => {
};
onClick 이벤트 추가<button onClick={handleClick}>추가</button>
handleClick 함수 안에 try-catch 문 & async, await 코드 추가const handleClick = async () => {
try{
// .post<ClientDto> 는 res.data 의 type 을 결정해준다
const {data} = await axios.post<ClientDto>("/api/v1/clients", dto);
// data 는 ClientDto type 이다
// 여기서는 서버에 새로 데이터를 요청하지 않고 응답된 내용을 바로 list 에 추가해 보자
setList([...list, data]);
} catch(err){
console.log(err);
}
};

function Fortune(props) {
return <>
</>
}
<h3>오늘의 운세</h3>
<p style={{color:props.color}}>{props.fortuneToday}</p>
FortuneProps 타입 추가export type FortuneProps = {
color : string; // 글자의 색상
fortuneToday : string; // 운세 정보
};
props 의 타입을 FortuneProps 로 선언import type { FortuneProps } from '../types/type';
function Fortune(props:FortuneProps) {
return <>
<h3>오늘의 운세</h3>
<p style={{color:props.color}}>{props.fortuneToday}</p>
</>
}
function App8() {
return <>
</>
}
Fortune 사용<div className="container">
<h1>인덱스 페이지</h1>
<Fortune />
</div>

<Fortune color="blue" fortuneToday={"동쪽으로 가면 귀인을 만나요"}/>

function App9() {
return <>
</>
}
파일 탐색기를 열어 react 폴더에서 cmd 창 열기
npm create electron-vite@latest
y
hello-electron 로 설정하고 탬플릿을 React 로 설정√ Project name: ... hello-electron
√ Project template: » React

hello-electron 로 이동cd hello-electron
dependency 설치npm install
npm run dev

electron
src
화면 UI 담당
App.tsx 에 예시로 테스트할 p 요소 코드 추가
function App() {
return <>
<p>나의 테스크탑 Application</p>
</>
}
