9:29 학원 도착
<9:30 1교시>
주소 창의 #은 주소창의 ID 같은 것이라 생각하면 된다..?라고 하는 거 같은데
예를 들어 localhost:9000/home에 대한 요청을 할 때, 그 home에는 html 요소의 id가 one, two, three인 div 같은 것이 있을 수 있는데, localhost:9000/home#one이라고 하면 그 페이지 내에서의 책갈피로서 스크롤 이동을 가능하게 해주는데,
이런 관점에서 봤을 때
localhost:3000/#/posts?pageNum=1이라고 했을 때 웹브라우저 입장에서는 이게 localhost:3000이라는 최상위 경로를 요청했고, 그에 대해 id가 posts?pageNum=1인 콘텐츠를 보여주고 있는것이라고 이해하면 됨.
src의 pages에 post.jsx가 있는데 여기서 첨으로 useSearchParams라는 훅을 사용했다.
useSearchParams({pageNum:1, condition:"", keyword:""})라는 식
이것은 마치 ?pageNum=1&condition=keyword=이라고 초기값을 넣어준 것과 같다.
pageNum을 알고 싶다면 params.get("pageNum")이라고 작성하면 된다.
useEffect 함수는 Post컴포넌트가 활성화 되는 시점에 한번 호출되고 또한 params에 변화가 생겼을 때 호출된다.
보이는 글을 마크업 형식으로 해석해주는 코드
파일이름에 module이 들어가 있는 애들은 import 한 곳에서만 선택적으로 사용하겠다는 의미.
<10:30 2교시>
<11:30 3교시>
alert창이나 confirm 창을 components로서 관리하려고 함.
<12:30 4교시>
혼자 힘으로 PostUpdate만들어보기 중
삽질 과정
밥먹기 전
import axios from 'axios';
import React, { useEffect, useRef, useState } from 'react';
import { Button, FloatingLabel, Form } from 'react-bootstrap';
import { useSelector } from 'react-redux';
import { useNavigate, useParams, useSearchParams } from 'react-router-dom';
import AlertModal from '../components/AlertModal';
import { initEditor } from '../editor/SmartEditor';
function PostUpdate(props) {
// "/posts/:num" 에서 num 에 해당되는 경로 파라미터 값 읽어오기
const {num} = useParams()
//글 하나의 정보를 상태값으로 관리
const [state, setState]=useState({})
//검색 키워드 관련처리
const [params, setParams]=useSearchParams({
condition:"",
keyword:""
});
//로그인된 userName
const userName = useSelector(state => state.userInfo.userName);
//SmartEditor 에 작성한 내용을 textarea 의 value 로 넣어 줄때 필요한 함수가 editorTool 이다
const [editorTool, setEditorTool] = useState([])
useEffect(()=>{
//initEditor() 함수를 호출하면서 SmartEditor 로 변환할 textarea 의 id 를 전달하면
//textarea 가 SmartEditor 로 변경되면서 에디터 tool 객체가 리턴된다.
setEditorTool(initEditor("content")); // initEditor() 함수를 호출해야 SmartEditor 가 초기화된다.
}, [])
//입력한 내용을 얻어오기 위한 useRef()
const inputTitle=useRef()
const inputContent=useRef()
//경로 이동을 할 함수
const navigate = useNavigate()
//알림 모달을 띄울지 말지를 state로 관리하기
const [modalShow, setModalShow]=useState(false);
useEffect(()=>{
const query=new URLSearchParams(params).toString();
axios.get(`/posts/${num}${params.get("condition") ? "?"+query : ""}`)
.then(res=>{
//글하나의 정보를 상태값에 넣어주고
setState(res.data);
})
.catch(error=>{
console.log(error);
});
}, []);
return (
<>
<AlertModal show={modalShow} message="글이 수정되었습니다" onYes={()=>{
navigate(`/posts/${state.num}`)
setModalShow(false);
}}/>
<h1>글 수정하기</h1>
<Form>
<FloatingLabel label="제목" className="mb-3" controlId="title">
<Form.Control ref={inputTitle} type="text">{state.title}</Form.Control>
</FloatingLabel>
<Form.Group className="mb-3" controlId="content">
<Form.Label>내용</Form.Label>
<Form.Control ref={inputContent} as="textarea" rows="10"><div dangerouslySetInnerHTML={{__html:state.content}}></div></Form.Control>
</Form.Group>
<Button type="submit" onClick={(e)=>{
//폼 제출 막기
e.preventDefault();
//에디터 tool 을 이용해서 SmartEditor 에 입력한 내용을 textarea 의 value 값으로 변환
editorTool.exec();
//입력한 제목과 내용을 읽어와서
const title=inputTitle.current.value;
const content=inputContent.current.value;
//axios 를 이용해서 api 서버에 전송
axios.patch(`/posts/${state.num}`, {title, content})
.then(res=>{
setModalShow(true)
})
.catch(error=>{
console.log(error);
});
}}>저장</Button>
</Form>
</>
);
}
export default PostUpdate;
점심 먹고 해본거
import axios from 'axios';
import React, { useEffect, useRef, useState } from 'react';
import { Button, FloatingLabel, Form } from 'react-bootstrap';
import { useSelector } from 'react-redux';
import { useNavigate, useParams, useSearchParams } from 'react-router-dom';
import AlertModal from '../components/AlertModal';
import { initEditor } from '../editor/SmartEditor';
function PostUpdate(props) {
// "/posts/:num" 에서 num 에 해당되는 경로 파라미터 값 읽어오기
const {num} = useParams()
//글 하나의 정보를 상태값으로 관리
const [state, setState]=useState({})
//검색 키워드 관련처리
const [params, setParams]=useSearchParams({
condition:"",
keyword:""
});
//로그인된 userName
const userName = useSelector(state => state.userInfo.userName);
//SmartEditor 에 작성한 내용을 textarea 의 value 로 넣어 줄때 필요한 함수가 editorTool 이다
const [editorTool, setEditorTool] = useState([])
useEffect(()=>{
//initEditor() 함수를 호출하면서 SmartEditor 로 변환할 textarea 의 id 를 전달하면
//textarea 가 SmartEditor 로 변경되면서 에디터 tool 객체가 리턴된다.
setEditorTool(initEditor("content")); // initEditor() 함수를 호출해야 SmartEditor 가 초기화된다.
}, [])
//입력한 내용을 얻어오기 위한 useRef()
const inputTitle=useRef()
const inputContent=useRef()
const onInput =()=>{
setState({ ...state, title:inputTitle, content:inputContent})
}
//경로 이동을 할 함수
const navigate = useNavigate()
//알림 모달을 띄울지 말지를 state로 관리하기
const [modalShow, setModalShow]=useState(false);
useEffect(()=>{
const query=new URLSearchParams(params).toString();
axios.get(`/posts/${num}${params.get("condition") ? "?"+query : ""}`)
.then(res=>{
//글하나의 정보를 상태값에 넣어주고
setState(res.data);
})
.catch(error=>{
console.log(error);
});
}, []);
return (
<>
<AlertModal show={modalShow} message="글이 수정되었습니다" onYes={()=>{
navigate(`/posts/${state.num}`)
setModalShow(false);
}}/>
<h1>글 수정하기</h1>
<Form>
<Form.Group className="mb-3" controlId="title">
<Form.Label>제목</Form.Label>
<Form.Control ref={inputTitle} type="text" onChange={onInput} placeholder={state.title}/>
</Form.Group>
<Form.Group className="mb-3" controlId="content">
<Form.Label>내용</Form.Label>
<Form.Control ref={inputContent} as="textarea" onChange={onInput} rows="10" value={state.content}/>
</Form.Group>
<Button type="submit" onClick={(e)=>{
//폼 제출 막기
e.preventDefault();
//에디터 tool 을 이용해서 SmartEditor 에 입력한 내용을 textarea 의 value 값으로 변환
editorTool.exec();
//입력한 제목과 내용을 읽어와서
const title=inputTitle.current.value;
const content=inputContent.current.value;
//axios 를 이용해서 api 서버에 전송
axios.patch(`/posts/${state.num}`, {title, content})
.then(res=>{
setModalShow(true)
})
.catch(error=>{
console.log(error);
});
}}>저장</Button>
</Form>
</>
);
}
export default PostUpdate;
<14:30 5교시>
package.json에 jsontokens를 없애기
npmjs.com에서는 npm으로 설치할 수 있는 목록을 검색할 수 있다.
jwtDecode로 바꾸고 payload란 방이 없으니 바로 decoded.sub 등으로 바꾸기(App, loginModal,)
수정 컴포넌트 동작 시킬 준비 PostUpdateForm.jsx로 만들어주기. 나는 걍 PostUpdate라고 한거에 수정할 거 있으면 수정해야지. 점심시간에 기본적인건 해놨는데 수정 내용이 제대로 전달되지 않는게 아무래도 API 요청 부분을 잘못한 거 같음
샘이한거랑 내가 한 거 다른거 위주로 살며봐야지.
- 샘은 /post/:num/edit이라고 path를 정했음. 이게 나아보여서 내껏도 바꿈.
-샘은 onClick ={()=>{ navigate(`/posts/${state.num}/edit`)) }}이라고 작성하심
일단 함수를 호출하고 async와 await이 있을 때 promise가 해결될 때까지 기다린다.
then 함수에서 res 값에 들어오는 걸 await로 기다리고 있다가
응답이 오면 try~catch가 실행된다.
async await를 사용하는 장점은 const res=await ~~ 형식을 여러줄을 연달아 쓸 수 있다는 것이 장점이다.
응답을 받아올 것이 여러개일 때 사용하기 용이하다는 것.
샘이랑 한 코드
<15:30 6교시>
스프링부트 서버에 컨트롤러 설정하기
선생님 코드
// src/pages/PostUpdateForm.jsx
import axios from 'axios';
import React, { useEffect, useRef, useState } from 'react';
import { Button, FloatingLabel, Form } from 'react-bootstrap';
import { useNavigate, useParams } from 'react-router-dom';
import { initEditor } from '../editor/SmartEditor';
import AlertModal from '../components/AlertModal';
function PostUpdateForm(props) {
//수정할 글번호 추출 "/posts/:num/edit" 에서 num 에 해당되는 경로 파라미터 값 읽어오기
const {num} = useParams();
//SmartEditor 에 작성한 내용을 textarea 의 value 로 넣어 줄때 필요한 함수가 editorTool 이다
const [editorTool, setEditorTool] = useState([])
// component 가 활성화 되는 시점에 호출되는 함수
useEffect(()=>{
// initEditor() 함수를 호출해야 SmartEditor 가 초기화 된다.
setEditorTool(initEditor("content"));
//비동기로 동작(호출하면 바로 리턴하지만 안에 있는 code 는 모두 실행된 상태가 아닌 비동기 함수)
const fetchPost = async ()=>{
try{
const res = await axios.get(`/posts/${num}`);
//글정보를 콘솔창에 출력하기
console.log(res.data);
//글 제목과 내용을 input 요소에 넣어주기
inputTitle.current.value=res.data.title;
inputContent.current.value=res.data.content;
}catch(error){
console.log(error);
}
};
fetchPost();
console.log("fetchPost() 함수 호출함");
}, []);
//제목을 입력할 input type="text" 와 내용을 입력할 textarea 의 참조값을 관리하기 위해
const inputTitle=useRef();
const inputContent=useRef();
const handleSubmit = (e)=>{
e.preventDefault();
//에디터 tool 을 이용해서 SmartEditor 에 입력한 내용을 textarea 의 value 값으로 변환
editorTool.exec();
//입력한 제목과 내용을 읽어와서
const title=inputTitle.current.value;
const content=inputContent.current.value;
//수정반영 요청을 하는 비동기 함수
const updatePost = async ()=>{
try{
const res = await axios.patch(`/posts/${num}`, {title, content});
console.log(res.data);
//모달을 띄운다음 글자세히 보기로 이동되도록 한다.
setShowModal(true);
}catch(error){
console.log(error);
}
};
updatePost();
}
const [showModal, setShowModal] = useState(false);
const navigate = useNavigate();
return (
<>
<AlertModal show={showModal} message="수정했습니다" onYes={()=>{
navigate(`/posts/${num}`);
}}/>
<h1>글 수정 양식 입니다</h1>
<Form>
<FloatingLabel label="제목" className='mb-3' controlId='title'>
<Form.Control ref={inputTitle} type="text"/>
</FloatingLabel>
<Form.Group className='mb-3' controlId='content'>
<Form.Label>내용</Form.Label>
<Form.Control ref={inputContent} as="textarea" style={{height:"300px"}}/>
</Form.Group>
<Button type="submit" onClick={handleSubmit}>수정확인</Button>
<Button type="reset" variant='danger'>취소</Button>
</Form>
</>
);
}
export default PostUpdateForm;
추가하는 기능 : 수정 취소를 누르면 원래 정보가 돌아오게 했어야 하는데 제목이 저장은 됐는데 자꾸 사라져있는게 버튼 타입이 reset이어서 그런걸 발견해서 handleReset에도 preventdefault를 추가할 수 있도록 샘을 도왔다 므하하
import axios from 'axios';
import React, { useEffect, useRef, useState } from 'react';
import { Button, Form } from 'react-bootstrap';
import { useNavigate, useParams} from 'react-router-dom';
import AlertModal from '../components/AlertModal';
import { initEditor } from '../editor/SmartEditor';
function PostUpdate(props) {
// 수정할 글번호 추출"/posts/:num/edit" 에서 num 에 해당되는 경로 파라미터 값 읽어오기
const {num} = useParams()
//SmartEditor 에 작성한 내용을 textarea 의 value 로 넣어 줄때 필요한 함수가 editorTool 이다
const [editorTool, setEditorTool] = useState([])
//원래 글의 내용을 state에 저장해 놓기
const [savedData, setSavedData] = useState();
//제목 입력할 input type="text"와 내용을 입력할 textarea의 참조값을 관리하기
const inputTitle=useRef()
const inputContent=useRef()
//component가 활성화 되는 시점에 호출되는 함수
useEffect(()=>{
//initEditor()함수를 호출해야 SmartEditor가 초기화 된다.
//initEditor() 함수를 호출하면서 SmartEditor 로 변환할 textarea 의 id 를 전달하면
//textarea 가 SmartEditor 로 변경되면서 에디터 tool 객체가 리턴된다.
setEditorTool(initEditor("content")); // initEditor() 함수를 호출해야 SmartEditor 가 초기화된다.
//비동기로 동작(호출하면 바로 리턴하지만 안에 있는 코드는 모두 실행된 상태가 아닌 비동기 함수)
const fetchPost=async ()=>{
try{
const res=await axios.get(`/posts/${num}`)
console.log(res.data)//글정보를 콘솔창에 출력
inputTitle.current.value=res.data.title;
inputContent.current.value=res.data.title;
setSavedData(res.data);
}catch(error){
console.log(error)
}
}
fetchPost();
console.log("fetch함수 호출함")//이 함수는 호출하면 바로 리턴한다 =console.log("fetchPost()함수를 호출함")
}, [])
const handleSubmit = (e)=>{
//폼 제출 막기
e.preventDefault();
//에디터 tool 을 이용해서 SmartEditor 에 입력한 내용을 textarea 의 value 값으로 변환
editorTool.exec();
console.log("에디터툴툴")
//입력한 제목과 내용을 읽어와서
const title=inputTitle.current.value;
const content=inputContent.current.value;
console.log("데이터 읽기")
//수정 반영 요청을 하는 비동기 함수
const updatePost= async ()=>{
try{
const res=await axios.patch(`/posts/${num}`, {title,content})
console.log(res.data)
//모달 띄우기
setModalShow(true);
//글 자세히 보기로 이동
}catch(error){
console.log(error)
}
}
updatePost()
console.log("업데이트포스트함수호출출")
//axios 를 이용해서 api 서버에 전송
// axios.patch(`/posts/${state.num}`, {title, content})
// .then(res=>{
// setModalShow(true)
// })
// .catch(error=>{
// console.log(error);
// });
}
//경로 이동을 할 함수
const navigate = useNavigate()
//알림 모달을 띄울지 말지를 state로 관리하기
const [modalShow, setModalShow]=useState(false);
const handleReset = (e)=>{
e.preventDefault();
//title을 원상복구
inputTitle.current.value=savedData.title;
//smartEditor에 출력된 내용을 원상 복구
editorTool.setContents(savedData.content);
}
return (
<>
<AlertModal show={modalShow} message="글이 수정되었습니다" onYes={()=>{
navigate(`/posts/${num}`)
setModalShow(false);
}}/>
<h1>글 수정하기</h1>
<Form>
<Form.Group className="mb-3" controlId="title">
<Form.Label>제목</Form.Label>
<Form.Control ref={inputTitle} type="text" />
</Form.Group>
<Form.Group className="mb-3" controlId="content">
<Form.Label>내용</Form.Label>
<Form.Control ref={inputContent} as="textarea" rows="10"/>
</Form.Group>
<Button type="submit" onClick={handleSubmit}>수정 확인</Button>
<Button type="reset" variant='danger' onClick={handleReset}>취소</Button>
</Form>
</>
);
}
export default PostUpdate;
<16:30 7교시 ~8교시>
시험
'자바풀스택 과정 > 자바 풀 스택 : 수업내용정리' 카테고리의 다른 글
자바 풀 스택 3/20 하루 기록 078 (0) | 2025.03.20 |
---|---|
자바 풀 스택 3/19 하루 기록 077 (0) | 2025.03.19 |
자바 풀 스택 3/17 하루 기록 075 (0) | 2025.03.17 |
자바 풀 스택 3/14 오후 기록 074-2 (0) | 2025.03.14 |
자바 풀 스택 3/14 오전 기록 074-1 (0) | 2025.03.14 |