-
카테고리
-
세부 분야
프론트엔드
-
해결 여부
해결됨
infinite scroll에서 최초 랜더링한 페이지가 한페이지에 안나올때 추가로 페이지를 불러 올수 있나요?
23.07.29 23:45 작성 23.07.29 23:57 수정 조회수 352
0
만약 Page의 단위를 5로 잡아서
최초 랜더링한 페이지가 스크롤이 되지않는다면
onScroll 이벤트가 발생하지 않으니 setSize 이벤트도 발생할수 없습니다.
이렇게 최초 데이터의 개수가 모자라서 이벤트 자체가 발생하지 않으면 별개의 이벤트로 scroll이 가능할때까지 페이지를 불러와야 하는데 좋은 방법이 잇는가요?
페이지를 5개로 잡을떄
페이지를 20개로 잡을떄
참조 코드
import ChatBox from '@components/ChatBox';
import ChatList from '@components/ChatList';
import useInput from '@hooks/useInput';
import { Header, Container } from '@pages/DirectMessage/styles';
import fetcher from '@utils/fetcher';
import makeSection from '@utils/makeSection';
import axios from 'axios';
import gravatar from 'gravatar';
import React, { FC, FormEventHandler, useCallback, useEffect, useRef, useState } from 'react';
import Scrollbars from 'react-custom-scrollbars-2';
import { useParams } from 'react-router';
import useSWR from 'swr';
import useSWRInfinite from 'swr/infinite';
const PAGE_SIZE = 5;
const DirectMessage: FC = () => {
const { workspace, id } = useParams();
const { data: myData } = useSWR<IUser, false>('/api/users', fetcher);
const { data: userData } = useSWR<IUser, false>(`/api/workspaces/${workspace}/users/${id}`, fetcher);
const [chat, onChangeChat, setChat] = useInput('');
// const scrollbarRef = useRef(null);
const {
data: chatData,
mutate: mutateChat,
setSize,
} = useSWRInfinite<IDM[]>(
(index) => `/api/workspaces/${workspace}/dms/${id}/chats?perPage=${PAGE_SIZE}&page=${index + 1}`,
fetcher,
);
const isEmpty = chatData?.[0]?.length === 0;
const isReachingEnd = isEmpty || (chatData && chatData[chatData.length - 1]?.length < PAGE_SIZE);
const chatSection = makeSection(chatData ? [...chatData].flat().reverse() : []);
const onSubmitForm = useCallback<FormEventHandler>(
(event) => {
event.preventDefault();
if (!chat || !chat?.trim()) {
return;
}
axios
.post(`/api/workspaces/${workspace}/dms/${id}/chats`, {
content: chat,
})
.then(() => {
mutateChat();
setChat('');
})
.catch(console.error);
console.log('제출');
},
[chat, id, mutateChat, setChat, workspace],
);
const scrollbarRef = useRef<Scrollbars>(null);
return !userData || !myData || !chatData ? null : (
<Container>
<Header>
<img src={gravatar.url(userData.email, { s: '24px', d: 'retro' })} alt={userData.nickname} />
<span>{userData.nickname}</span>
</Header>
<ChatList
chatSections={chatSection}
isEmpty={isEmpty}
isReachingEnd={isReachingEnd}
setSize={setSize}
ref={scrollbarRef}
/>
<ChatBox
onSubmitForm={onSubmitForm}
chat={chat}
onChangeChat={onChangeChat}
placeholder={`Message ${userData.nickname}`}
otherData={[userData]}
/>
</Container>
);
};
export default DirectMessage;
import Chat from '@components/Chat';
import { ChatZone, Section, StickyHeader } from '@components/ChatList/styles';
import React, { FC, MutableRefObject, forwardRef, useCallback } from 'react';
import { Scrollbars, positionValues } from 'react-custom-scrollbars-2';
interface Props {
chatSections: { [key: string]: (IDM | IChat)[] };
isEmpty: boolean;
isReachingEnd?: boolean;
setSize: (f: (size: number) => number) => Promise<(IDM | IChat)[][] | undefined>;
}
const ChatList = forwardRef<Scrollbars, Props>(({ chatSections, isReachingEnd, isEmpty, setSize }, scrollRef) => {
const onScroll = useCallback(
(values: positionValues) => {
if (values.scrollTop === 0 && !isReachingEnd) {
setSize((size) => size + 1).then(() => {
const current = (scrollRef as MutableRefObject<Scrollbars>)?.current;
if (current) {
current.scrollTop(current.getScrollHeight() - values.scrollHeight);
}
});
}
},
[isReachingEnd, scrollRef, setSize],
);
return (
<ChatZone>
<Scrollbars autoHide ref={scrollRef} onScrollFrame={onScroll}>
{Object.entries(chatSections).map(([dateData, chatData]) => (
<Section className={`section-${dateData}`} key={dateData}>
<StickyHeader>
<button>{dateData}</button>
</StickyHeader>
{chatData.map((chat) => (
<Chat key={chat.id} data={chat} />
))}
</Section>
))}
</Scrollbars>
</ChatZone>
);
});
export default ChatList;
답변을 작성해보세요.
답변 1