주요 기능 | 게시판 - itsyuna/Foot-Salon GitHub Wiki
Redux Toolkit, Thunk를 사용하여 Data, Store, Module 관리
React Hook Form을 활용하여 form 작성
로그인 시 게시글 작성 / 게시글 보기 가능
게시글,댓글 - 작성자 기준 '수정' / '삭제' 버튼 활성화
- 업로드 파일 미리 보기
- 댓글 작성/읽기/업데이트/삭제
- 댓글 수 표시
- '첫 댓글', 수정 시 수정 시각 & '수정됨' 문구 추가
store/playBoard.tsx
export const fetchPlayBoard = createAsyncThunk(
"board/fetchPlayBoard",
async () => {
const collectData = collection(
dbService,
"play"
) as CollectionReference<BoardContents>;
const orderData = query(collectData, orderBy("dateTime", "desc"));
const querySnapshot = await getDocs(orderData);
const playBoard = querySnapshot.docs.map((doc) => ({
id: doc.id,
board: doc.data(),
}));
return playBoard;
}
);
const initialBoardState: BoardListItems[] = [];
const boardSlice = createSlice({
name: "playBoard",
initialState: {
boardArray: initialBoardState,
},
reducers: {},
extraReducers: (builder) => {
builder.addCase(fetchPlayBoard.fulfilled, (state, action) => {
state.boardArray = action.payload;
});
},
});
export const boardActions = boardSlice.actions;
export default boardSlice.reducer;
PostEditor.tsx
const PostEditor = ({ isEdit }: { isEdit: boolean }) => {
...
// React hook form의 useForm 사용
const {
handleSubmit,
control,
formState: { errors },
} = useForm<BoardFormData>();
...
return isEdit && !targetPost ? (
// Edit 모드 & 해당 게시글이 없을 때 에러 메시지 표시
<NoPostMessage />
) : (
<BoardCard>
<Form onSubmit={handleSubmit(onSubmit)}>
<section>
<CategoryBox>
<CategoryName>작성자</CategoryName>
<UserNickname>{userNickname}</UserNickname>
</CategoryBox>
<CategoryBox>
<CategoryName>리그</CategoryName>
<CategoryData>
// React hook form의 Controller 사용
<Controller
control={control}
defaultValue={targetPost?.board.league}
name="league"
rules={{
...(!isEdit && {
required: "필수 입력사항입니다.",
}),
}}
render={({ field }) => (
<Select
option={optionList}
onChange={field.onChange}
defaultValue={targetPost?.board.league}
backgroundColor="#f6edd9"
color="#379237"
border="#7a9972"
></Select>
)}
/>
</CategoryData>
// 필수 입력 사항에 빈 input이 있을 시 에러 메시지 표시
<ErrorText>{errors.league && errors.league.message}</ErrorText>
</CategoryBox>
...
BoardList.tsx
// 최신순/오래된 순으로 게시글 정렬
const getListByOption = useCallback(() => {
const compare = (a: BoardListItems, b: BoardListItems) => {
if (sortList === "latest") {
return (
new Date(b.board.createdAt).getTime() -
new Date(a.board.createdAt).getTime()
);
} else
return (
new Date(a.board.createdAt).getTime() -
new Date(b.board.createdAt).getTime()
);
};
// 원본 데이터를 보존하기 위해 copy해서 사용
const copyList: BoardListItems[] = JSON.parse(
JSON.stringify(boardByleague.map((item) => item))
);
const filterList = copyList.sort(compare);
return filterList;
}, [boardByleague, sortList]);
...
Commnets.tsx
const editCommentSubmitHandler = async (data: CommentFormData) => {
// 수정 시 수정 시각 반영
const editCommentItems = {
creatorId: userId,
userNickname,
contents: data.comment,
createdAt: getDate(),
dateTime: list.comment.dateTime,
isEdit: true,
};
...
}
return (
...
// 첫 댓글 & '수정됨' 문구 추가
<NicknameDate editComment={editComment}>
<h3>{list.comment.userNickname}</h3>
<h4>{list.comment.createdAt}</h4>
{idx === 0 && <FirstComment>첫 댓글</FirstComment>}
{list.comment.isEdit && <EditText>수정됨</EditText>}
</NicknameDate>
...
게시글 리스트

게시글 업로드
🔻 게시글 업로드
🔻 With photo (Preview)
게시글 보기

게시글 수정

게시글이 없을 시

댓글
🔻 댓글 보기
🔻 댓글 수정
에러 처리
🔻 해당 번호의 게시글이 없을 시