🔎
react-intersection-observer
특정 컴포넌트(요소태그),viewport안에 발견되었을때 스크롤된다.npm install react-intersection-observer --save
빨간색 밑부분에 div tag를 넣어준다.
- 앞에있는
ref
는 우리가 관찰할 요소를 알려주는데 사용- 뒤에있는
useInView
는 관찰할 요소가 화면에 나타나면true
, 사라지면false
를 반환하는 변수
import { useInView } from 'react-intersection-observer'
// 앞에있는 ref 는 우리가 관찰할 요소를 알려주는데 사용
// 뒤에있는 useInView 는 관찰할 요소가 화면에 나타나면 true, 사라지면 false를 반환하는 변수
const [ref, inView] = useInView(); // useInView() 는 true or false 를 반환한다.
useEffect(() => {
console.log('inView', inView);
}, [inView]);
return(
<div
ref={ref}
style={{
backgroundColor: 'red',
}}>
</div>
);
const [currentPage, setCurrentPage] = useState(1);
// 앞에있는 ref 는 우리가 관찰할 요소를 알려주는데 사용
// 뒤에있는 useInView 는 관찰할 요소가 화면에 나타나면 true, 사라지면 false를 반환하는 변수
const [ref, inView] = useInView(); // useInView() 는 true or false 를 반환한다.
useEffect(() => {
let tmp = async () => {
if (accessToken === null) return;
if (inView === false) return;
try {
let res = await axios.get(`/api/comments?activityId=${props.activityId}&limit=${3}&page=${currentPage}`, // 3개씩 가져오기
{
headers: { Authorization: `Bearer ${accessToken}` }
})
setCurrentPage(currentPage + 1);
setCommentList([...commentList, ...res.data]); // 기존 댓글(commentList)과, 새로운 댓글을 추가해준다.
} catch (err) {
alert('댓글목록 오류');
}
}
tmp();
}, [props.activityId, accessToken, inView]);
inView가 true 일때(빨간부분에 도달하면),
app.get('/api/comments', async (req, res) => {
const activityId = Number(req.query.activityId);
const limit = Number(req.query.limit); //한페이지에 보여줄 댓글 갯수
const page = Number(req.query.page); //보여줄 페이지
const offset = (page - 1) * limit; //건너뛸 댓글 갯수
let sql = `
select * from tbl_comments
where activity_id = ?
order by created_date asc
limit ? offset ?;
`;
try {
const token = req.headers.authorization.replace('Bearer ', '');
let user = jwt.verify(token, process.env.JWT_SECRET);
let [results] = await pool.query(sql, [activityId, limit, offset])
results = results.map((el) => ({ ...el, owner: el.writer_email === user.email })); //객체를 만드는 중괄호
console.log(results);
res.json(results);
} catch (err) {
res.status(500).json('오류발생');
}
})
그런데 여기서 문제❗️
처음에 댓글이 3개 보이는데, 거기서 댓글을'마지막댓글'
을 추가하면,
...commentList, ...res.data]
기존에 있는거에, 마지막에 추가한걸 추가하라고했는데,
근데 데이터 베이스는 댓글이 더 있잖아❓
그래서'마지막댓글이'
처음에 댓글이 3개 보인후, 그바로뒤에도 있고,
또 원래있던 데이터 베이스는 댓글 맨뒤에도 또'마지막댓글'
이 출력되어서
2개의'마지막댓글'
이 있다. 사이에 끼어서 들어간다.
그래서❗️댓글목록을 끝까지 다 가져온 상태라면 직접 화면에도 보이게 추가해준다.
const [isEnd, setIsEnd] = useState(false); // 댓글을 끝까지 다 가져왔다면 true 아니면 false
useEffect(() => {
let tmp = async () => {
if (accessToken === null) return;
if (inView === false) return;
if (isEnd === true) return; //🌟추가코드
try {
let res = await axios.get(`/api/comments?activityId=${props.activityId}&limit=${3}&page=${currentPage}`, // 3개씩 가져오기
{
headers: { Authorization: `Bearer ${accessToken}` }
})
setCurrentPage(currentPage + 1);
//댓글목록을 끝까지 다 가져온 상태라면 직접 화면에도 보이게 추가해준다.
if (res.data.length === 0) {//🌟추가코드
setIsEnd(true);
return;
}
setCommentList([...commentList, ...res.data]); // 기존 댓글(commentList)과, 새로운 댓글을 추가해준다.
} catch (err) {
alert('댓글목록 오류');
}
}
tmp();
}, [props.activityId, accessToken, inView]);
const onCommentClick = async () => {
try {
let res = await axios.post('/api/comments', {
content,
activityId: props.activityId
},
{
headers: { Authorization: `Bearer ${accessToken}` }
}
);
if (isEnd === true) { //🌟추가코드
setCommentList([...commentList, res.data]); // 기존 댓글(commentList)과, 새로운 댓글을 추가해준다.
}
alert('댓글작성 성공!');
setContent('');
} catch (err) {
alert('댓글작성 오류');
}
}; //body에다가 content를 담아서 express로 보내준다.