- 단어 수정 시
- 게시글 수정 시
▶ 사진은 변경하지 않음(링크에 추가만 한 상황)
▶ 기존에 작성한 글에 내용을 추가하는 경우 변경할 수 있도록 함
draft.mainPosts.find((v) => v.id === action.data.PostId).content = action.data.content
editMode는 true면 textArea를 보여주고 false면 기존 게시글을 보여줌
const [editMode, setEditMode] = useState(false)
description의 PostCardContent Component 만들고 editMode 추가
editMode일 때 ? textarea : 기존 값
postData는 고정값: 서버로부터 온 값
const [editText, setEditText] = useState(postData);
onChange={onChangeText}
const onChangeText = useCallback((e) => {
setEditText(e.target.value);
})
수정 시 수정, 취소 버튼 한 개 더 필요
editMode를 false로 만들려면 onCancleUpdate, onChangePost는 부모 컴포넌트에서 조작해야 함
const onChangePost = useCallback((editText) => () => {
dispatch({
type: UPDATE_POST_REQUEST,
data: {
POSTId: post.id,
content: editText,
}
})
})
수정 버튼에 onClick={onChangePost(editText)}
이미 업로드된 이미지에 대한 데이터와 새로 업로드할 이미지에 대한 데이터 두 개로 분리해서 관리
-> 새로운 이미지 추가하는 것 + 기존 이미지 삭제하는 것도 대응 가능
기존 initialState {
mainPosts: [
{
id: shortId.generate(),
content:
"It is a long established fact that a reader will be distracted by the readable content of a page when looking at its layout. The point of using Lorem Ipsum is that it has a more-or-less normal distribution of letters, as opposed to using 'Content here, content here', making it look like readable English.",
User: {
id: shortId.generate(),
nickname: "test",
},
Images: ["https://picsum.photos/400"],
Comments: [],
},]
revisePostLoading: false, //게시글 수정 중
revisePostComplete: false,
revisePostError: null,
}
//게시글 수정
revisePostRequest: (state) => {
state.revisePostLoading = true;
state.revisePostError = null;
state.revisePostComplete = false;
},
revisePostSuccess: (state, action) => {
const data = action.payload;
state.revisePostLoading = false;
state.revisePostComplete = true;
//data.id가 숫자이기 때문에 가능한 것
state.mainPosts.splice(data.id, 1, {
id: shortId.generate(),
content: data.content,
User: {
id: shortId.generate(),
nickname: "test",
},
Images: ["https://picsum.photos/500"], //임시
Comments: [],
});
},
revisePostFailure: (state, action) => {
state.revisePostLoading = false;
state.revisePostError = action.error;
},
function* revisePost(action) {
try {
const data = action.payload;
yield put(revisePostSuccess(data));
} catch (err) {
console.error(err);
yield put(revisePostFailure(err));
}
}
function* revisePost_Req() {
yield takeLatest(revisePostRequest.type, revisePost);
}
export const postSagas = [
fork(revisePost_Req),
];
const dispatch = useDispatch();
const { mainPosts } = useSelector((state) => state.post);
const [editMode, setEditMode] = useState(false);
const onClickRevise = useCallback( //처음 수정 버튼 누름
(e) => {
setId(e.target.value);
setEditMode(true);
},
[id]
);
const onRevisePost = useCallback( //textarea로 바뀌고 최종 수정 버튼 누름
(editText, index) => () => {
setEditMode(false);
console.log("editText", editText);
console.log("onRevisePost index", index);
dispatch(revisePostRequest({ id: index, content: editText }));
},
[mainPosts]
);
const onCancleRevisePost = useCallback(() => {
setEditMode(false);
}, []);
{mainPosts.map((post, index) => {
return (
{editMode ? null : (
<Popover>
<>
<Popover.Button className="rounded-md px-3 py-2 text-base">
<div>
<EllipsisHorizontalIcon className="h-9 w-9" />
</div>
</Popover.Button>
<Transition
as={Fragment}
enter="transition ease-out duration-200"
enterFrom="opacity-0 translate-y-1"
enterTo="opacity-100 translate-y-0"
leave="transition ease-in duration-150"
leaveFrom="opacity-100 translate-y-0"
leaveTo="opacity-0 translate-y-1"
>
<Popover.Panel className="absolute mt-1 w-16 h-10">
<div className="overflow-hidden rounded-lg shadow-lg ring-1 ring-black ring-opacity-5">
<div className="bg-light-beige p-1">
<button
value={index}
onClick={onClickRevise}
className="flow-root rounded-md px-2 py-2 transition duration-150 ease-in-out hover:bg-light-beige focus:outline-none focus-visible:ring focus-visible:ring-orange-500 focus-visible:ring-opacity-50"
>
수정
</button>
<button
value={index}
onClick={onRemovePost}
className="flow-root rounded-md px-2 py-2 transition duration-150 ease-in-out hover:bg-light-beige focus:outline-none focus-visible:ring focus-visible:ring-orange-500 focus-visible:ring-opacity-50"
>
삭제
</button>
</div>
</div>
</Popover.Panel>
</Transition>
</>
</Popover>
)}
</div>
</header>
<PostCardContent
editMode={editMode}
//아래의 값들 전달
onCancleRevisePost={onCancleRevisePost}
onRevisePost={onRevisePost}
image={post.Images}
content={post.content}
index={index}
/>
...})
import React, { useState } from "react";
import { useCallback } from "react";
const PostCardContent = ({
image,
content,
editMode,
onRevisePost,
onCancleRevisePost,
index,
}) => {
const [editText, setEditText] = useState(content); //수정할 텍스트
const onChangeText = useCallback((e) => {
setEditText(e.target.value);
});
return (
<>
{editMode ? (
<div>
<img src={image} alt="post.Images" className="w-1/2 mx-auto block" />
<textarea
id="message"
rows="4"
className="ml-4 block p-2.5 w-11/12 h-full text-sm text-gray-900 bg-white rounded-lg border border-gray-300 focus:ring-blue-500 focus:border-blue-500"
onChange={onChangeText}
>
{content}
</textarea>
<div className="flex justify-end items-center mt-2 mr-4">
<button
onClick={onRevisePost(editText, index)} //editText와 index 값 전달
className="mr-2 px-1 h-9 bg-light-beige rounded-md font-bold focus:bg-light-green focus:text-white"
>
수정
</button>
<button
onClick={onCancleRevisePost}
className="px-1 h-9 bg-light-beige rounded-md font-bold focus:bg-red-500 focus:text-white"
>
취소
</button>
</div>
<small className="text-gray-400 m-4">2 hours ago</small>
</div>
) : (
<div>
<img src={image} alt="post.Images" className="w-1/2 mx-auto block" />
<p className="p-4">{content}</p>
<small className="text-gray-400 m-4">2 hours ago</small>
</div>
)}
</>
);
};
export default PostCardContent;