Warning: validateDOMNesting(...): <form> cannot appear as a descendant of <form>.
react-dom.development.js:86 경고: validationDOMNesting(...): 은 의 자손으로 나타날 수 없습니다. form태그 input태그를 꼭 소문자로 할 필요가 없음! const onBoardFormSubmitEvent = (event) => {
event.preventDefault();
alert("안녕!");
};
return (
<BoardDetailWrap>
<BoardDetailContainer>
<BoardDetailHeadBox>
<BoardDetailHeadText>댓글</BoardDetailHeadText>
</BoardDetailHeadBox>
<BoardDetailForm onSubmit={onBoardFormSubmitEvent}>
<BoardDetailInputBox>
<input
onChange={handleNicknameInputChange}
value={nickname}
type="text"
placeholder="작성자"
/>
<input
onChange={handlePasswordInputChange}
value={commentPassword}
type="text"
placeholder="비밀번호"
/>
</BoardDetailInputBox>
<BoardDetailCommentBox>
<input
value={onBoardComment}
onChange={handleCommentInputChange}
type="text"
placeholder="어떤 이야기를 나누고 싶으신가요?"
/>
<BoardDetailCommentBtn type="submit">
등록하기
</BoardDetailCommentBtn>
</BoardDetailCommentBox>
</BoardDetailForm>
</BoardDetailContainer>
</BoardDetailWrap>
);
};
styled component도 종류가 굉장히 많기 때문에 from뒤를 잘 봐야함
```jsx
// BoardDetailCommentListBox.jsx
import styled from "styled-components";
```
이건 mui에서 import하는 거기 때문에 mui가 필요한 경우에만 이렇게 import를 하는 거임
// BoardDetailCommentListBox.jsx
import styled from '@emotion/styled';
그리고 컴포넌트 내에서 styled를 줬으면 가져왔을 때 또 styled컴포넌트를 안줘도 됨
// BoardDetailCommentListBox.jsx
import React from "react";
import styled from "styled-components";
function BoardDetailCommentListBox() {
return <StyledCommentListBox>BoardDetailCommentListBox</StyledCommentListBox>;
}
export default BoardDetailCommentListBox;
const StyledCommentListBox = styled.div`
width: 100%;
`;
BoardDetailCommentWrite 내에서 쓸 때 이미 import할 때 styled도 적용이 된 상태이기 때문에 굳이 2번하지 않아도 됨
내가 만든 리덕스를 상원님이 하신 slice랑 toolkit으로 바꾸는 순서
리듀서 함수를 createSlice로 바꾸기
상원님의 코드를 참고해서 add부분의 createAsyncThunk 함수 만들기
slice의 extraReducers에 fullfilled일 경우 추가하기
2번 함수를 export해서 Page 컴포넌트 안에서 쓰기
thunk
서버에서 불러오고 싶다거나 dispatch전에 뭔가를 하고 싶을 때 청크를 씀
extraReducer
엑스트라리듀서에 리듀서 역할을 넣어야함
axios
서버랑 통신하는 라이브러리
async
dispatch를 하기 전에 어떤 작업을 하기 위해서 쓰는 애
서버로 포스트하는 애
dispatch를 만들어서 전달이 된다.
성공했을 때
promise - 대기 pending, 성공 fulfilled , 실패
createSlice
swift문 있는 reducer에서
create슬라이스 fulfilled
useLocation - 페이지의 정보를 가져오는 훅
props가 안돼서 -> params
css -> 글자가 몇자이상 넘어가면 침범 안 되게 말줄임표 ... 써보기
이게 뭐더라
```jsx
// boardSlick.js
// 이게 뭐더라..?
export const { _ } = boardSlice.actions;
```
서버쪽 삭제
await axios.delete(http://localhost:8080/boardComments/${payload}
);
fulfilled - ui에 보여주기
작업다하고 커밋, 상원님꺼 pull 하기
상원님의 모달창 관련 코드
const handleDeleteDetailComment = () => {
// 원래 있던 item의 password랑 모달창에 사용자가 입력한 pwValue거 일치한다면
const resDelete = boardComment.filter((item) => item.password === pwValue);
// resDelete의 length가 0보다 크면
if (resDelete.length > 0) {
dispatch(__deleteDetailComment(boardcommentId));
setPwValue("");
setIsOpen(false);
} else {
alert("비밀번호가 틀렸습니다.");
setIsOpen(false);
return;
}
};
handleDeleteDetailComment = handleModalCheckPasswordClick
boardCommentDelete = handleCommentDelete
BoardDetailCommentListBox = ArticleDetailPage
// BoardDetailCommentWrite.jsx
const onBoardFormSubmitEvent = (event) => {
event.preventDefault();
const newboardDetailComment = {
id: uuidv4(),
nickname: nickname,
commentPassword,
onBoardComment,
boardId,
};
dispatch(__BoardDetailComment(newboardDetailComment));
};
todos.js = boardDetailCommentList.js
configStore = configStore
상원님이 잡아놓은 ui를 쓰면서 같이 하기가 어려워서 따로 할 수가 없음
Input + TodoList = BoardDetailCommentWrite -> form 태그 위주로 같이 보기
const todos = const boardDetailComment
다시 해보기
221226 작성하기
그냥 내가 배웠던 투두리스트를 위주로
BoardDetailCommentWrite<부모컴포넌트> - 보드상세데이터
BoardDetailComment - 얘는 뭔지 모르겠음 있어도 그만 없어도 그만임
BoardDetailPage - BoardDetailCommentWrite의 <자식컴포넌트> - 보드상세ui페이지
todos.js = boardDetailCommentList.js
Input.
input 태그에는 label, variant, size, sx 안 먹음
label 대신에 placeholder
TextField로만 먹음 - ui라이브러리
인풋태그 안에 type="id", type="password"는 뭐지???
작성자, 비번, 코멘트를 인풋태그로 바꾸기 완료 !
게시판 detailpage ui 확인
뭘 나타낼건지? 투두리스트처럼 코멘트 리스트를 불러와야함
TodoList = CommentList
Wrap > Container > Box
queryString
use ref 로 기존에 걸 가져올 수 있음
redux-thunk
thunk
서버에서 불러오고 싶다거나 dispatch전에 뭔가를 하고 싶을 때 청크를 씀
엑스트라리듀서에 리듀서 역할을 넣어야함
엑시오스 - 서버랑 통신하는 라이브러리
dispatch를 만들어서 전달이 된다.
성공했을 때
promise - 대기 pending, 성공 fulfilled , 실패
createSlice
swift문 있는 reducer에서
dispatch를 하기 전에 어떤 작업을 하기 위해서 쓰는 애
서버로 포스트하는 애 - 에이싱크
create슬라이스 fulfilled
리듀서 함수를 createSlice로 바꾸기
상원님의 코드를 참고해서 add부분의 createAsyncThunk 함수 만들기
slice의 extraReducers에 fullfilled일 경우 추가하기
2번 함수를 export해서 Page 컴포넌트 안에서 쓰기
청크
useLocation - 페이지의 정보를 가져오는 훅
props가 안돼서 -> params
css -> 말줄임표 ... 써보기
deleteArticleComment
export const __deleteArticleComment = createAsyncThunk(
"deleteArticleComment",
async (payload, thunkAPI) => {
try {
await axios.delete(http://localhost:8080/articleComment/${payload}
);
return thunkAPI.fulfillWithValue(payload);
} catch (error) {
return thunkAPI.rejectWithValue(error);
}
}
);
isEditOpen - 비밀번호 모달창 열기 상태를 저장하는 애
true일 때 모달창이 뜨고
isEditClick - 수정버튼 클릭
editPassword - 모달창 비밀번호 값 받기
__deleteArticleComment - 청크함수
a태그는 inline요소라서 자리를 지킬 수 없음
position:'absolute'
다음엔 마진 안 먹고 top, bottom으로 주면 됨
__deleteDetailComment- 슬라이스부분
ui 변경
[__deleteDetailComment.fulfilled]: (state, action) => {
state.boardDetailComment = state.boardDetailComment.filter(
(state) => state.id !== action.payload
);
},
if문이랑 비교하기
item.password 랑 인풋 pwValue값이 같으면 삭제하기
삭제를 누르면 모달창이 뜨게
// 작성하는 로직임 / 삭제만 하면 됨
// const boardCommentDelete = (id) => () => {
// setIsDeleteModalOpen(true);
// setBoardCommentId(id);
// };
// 모달에 인풋 태그를만들어서 인풋에 있는 값을 받아온다음
// handleDeleteDetailCommentClick 안에서
// input의 value값이랑 비교
// 맞으면 삭제시켜주고, 틀리면 alert 하기