#03 리액트를 사용한 팬레터 웹사이트 개발
▼: DummyData로 리스트 UI 구현 및 클릭한 사람 데이터만 보이기 ▼
개인프로젝트 (리액트 팬레터 홈페이지 만들기 ) 과제 해설
- 팬레터 입력창(AddForm) : 팬레터 등록 기능 구현
- 유효성 검사 : 닉네임과 내용 미입력시 등록되지 않도록 적용
- 최대 글자수 제한 : 닉네임과 내용에 적용
(1) 팬레터 등록 기능 구현
[Home.jsx]
import AddForm from 'components/AddForm';
import Header from 'components/Header';
import LetterList from 'components/LetterList';
import React from 'react';
import styled from 'styled-components';
import { useState } from 'react';
import fakeData from 'fakeData.json';
export default function Home() {
const [activeMember, setActiveMember] = useState('민지');
const [letters, setLetters] = useState(fakeData);
return (
<Container>
<Header activeMember={activeMember} setActiveMember={setActiveMember} />
<AddForm setLetters={setLetters} />
<LetterList activeMember={activeMember} letters={letters} />
</Container>
);
}
▶ [기존] LetterList컴포넌트: 더미데이터(fakeData.json)으로 팬레터 생성 및 상태 변화 (letters, setLetters)
▶ [변경] AddForm컴포넌트: 여기에서도 더미데이터에 데이터 추가 형식
=> Home.jsx로 const [letters, serLetters] = useState(fakeData); 적용
자식 컴포넌트인 < LetterList > , < AddForm > 컴포넌트에 props로 내려주기
[Addform.jsx]
import React, { useState } from 'react';
import styled from 'styled-components';
import { v4 as uuid } from 'uuid';
export default function AddForm({ setLetters }) {
const [nickName, setNickName] = useState('');
const [content, setContent] = useState('');
const [member, setMember] = useState('민지');
const onAddLetter = (event) => {
event.preventDefault();
//유효성검사
if (!nickName || !content) return alert('닉네임과 내용은 필수값입니다.');
//추가 로직
const newLetter = {
createdAt: new Date(),
nickName,
avatar: null,
content,
writedTo: member,
id: uuid(),
};
setLetters((prev) => [newLetter, ...prev]);
};
return (
<Form onSubmit={onAddLetter}>
<InputWrapper>
<label>닉네임: </label>
<input
value={nickName}
onChange={(event) => setNickName(event.target.value)}
placeholder="최대 20글자까지 작성할 수 있습니다. "
maxLength={20}
/>
</InputWrapper>
<InputWrapper>
<label>내용: </label>
<textarea
value={content}
onChange={(event) => setContent(event.target.value)}
placeholder="최대 100글자까지 작성할 수 있습니다. "
maxLength={100}
/>
</InputWrapper>
<SelectWrapper>
<label>누구에게 보내실 건가요? </label>
<select value={member} onChange={(event) => setMember(event.target.value)}>
<option>민지</option>
<option>하니</option>
<option>다니엘</option>
<option>해린</option>
<option>혜인</option>
</select>
</SelectWrapper>
<BtnWrapper>
<button>팬레터 등록</button>
</BtnWrapper>
</Form>
);
}
▶[등록] 기능: form태그의 OnSubmit 이벤트 핸들러 이용
1) OnSubmit : 새로고침 기능이 default여서 event.preventDefault(); 적용해서 새로고침 안 되도록 설정
2) 유효성 검사
3) newLetter에 새로 입력되는 값 등록
- 등록 날짜 : new Data() 사용
- nickname,content는 useState로 set한 데이터들
- writeTo : <select>태그에서 선택한 멤버 => useState로 set한 데이터
- id : uuid() 사용 / 터미널에서 yarn add uuid 설치 + 많이 사용하는 {v4} 사용하기
(2) 유효성 검사 : 닉네임과 내용 미입력시 등록되지 않도록 적용
[Addform.jsx]
const onAddLetter = (event) => {
event.preventDefault();
//유효성검사
if (!nickName || !content) return alert('닉네임과 내용은 필수값입니다.');
}
▶ 닉네임 또는 내용이 없으면 리턴 + alert
(3) 최대 글자수 제한 : 닉네임과 내용에 적용
[Addform.jsx]
return (
<Form onSubmit={onAddLetter}
<InputWrapper>
<label>닉네임: </label>
<input
value={nickName}
onChange={(event) => setNickName(event.target.value)}
placeholder="최대 20글자까지 작성할 수 있습니다. "
maxLength={20}
/>
</InputWrapper>
<InputWrapper>
<label>내용: </label>
<textarea
value={content}
onChange={(event) => setContent(event.target.value)}
placeholder="최대 100글자까지 작성할 수 있습니다. "
maxLength={100}
/>
</InputWrapper>
▶input태그: maxLength={20} : 최대 20글자 제한
▶textarea태그 : maxLength={100} : 최대 100글자 제한
(4) Styled-components css 적용
[Addform.jsx]
const InputWrapper = styled.div`
display: flex;
justify-content: space-between; /*양쪽으로 붙이기 */
align-items: center;
& label {
width: 80px;
}
& input,
textarea {
width: 100%;
padding: 12px;
}
& textarea {
resize: none; /**사용자가 사이즈 수정 못하게 */
height: 80px;
}
`;
/*InputWrapper를 상속받아와서 오버라이드: 속성 덮어쓰기*/
const SelectWrapper = styled(InputWrapper)`
justify-content: flex-start;
& label {
width: 200px;
}
`;
const BtnWrapper = styled.div`
display: flex;
justify-content: flex-end;
align-items: center;
& button {
background-color: #e09dd3;
color: white;
font-size: 16px;
padding: 6px 12px;
cursor: pointer;
border: none;
}
`;
▶[포인트] 상속받아서 오버라이드로 속성 덮어쓰기 가능: const SelectWrapper = styled(InputWrapper)`
끝.
#05 리액트를 사용한 팬레터 웹사이트 개발
▼ : 상세화면 UI 구현 및 공통 컴포넌트 & 공통 함수 적용 ▼