React의 독단적인 특성에 대한 좋은 점 중 하나는 커뮤니티가 몇 가지 훌륭한 솔루션을 제시할 수 있다는 것입니다. 그 중 하나는 다른 프레임워크로 확장되었기 때문에 이제 tanstack-query로 가는 react-query입니다.
react-query 를 사용해야 한다면 아마도 . ap가 많은 네트워크 요청에 의존하는 경우 redux와 같은 것을 사용하기 전에 고려해야 합니다.
반응 쿼리는 데이터를 가져오는 방법에 대해 의견이 분분하다는 점을 명심하세요. 그 작업은 응답 및 오류/로딩 상태와 캐시 및 재시도를 처리하는 것입니다.
Add add your github personal access token in the field , to clear it from local storage click on the profile pic icon on the right end of the toolbar
const fetchdatas=async()=>{
const token ="token token token "
const url="https://api.github.com/user"
const res = await axios({
method: 'get',
url: url,
headers: {
Authorization: `Bearer ${token}`,
"Content-Type": "application/json"
},
})
// //console.log("response == ",res)
const user = res.data
// //console.log("authed user == ",user)
return user
}
graphql API
저는 graphql-request를 사용하겠습니다.
const USER = gql`
query getMiniUser($name: String!) {
user(login: $name) {
login
id
isFollowingViewer
viewerIsFollowing
bio
avatarUrl
isViewer
url
}
}
`;
const graphQLClient = new GraphQLClient(endpoint, headers);
const fetchData = async () => await graphQLClient.request(USER,{name:"tigawanna);
2단계: useQuery의 경우 쿼리 후크에 연결합니다.
const key =['user']
useQuery(key, fetchData,);
다음은 대부분의 프로젝트에서 계속 도달할 수 있는 몇 가지 팁과 요령입니다.
1 열쇠
react-quryke는 배열이며, 첫 번째 항목은 고유한 문자열이며 이름 변수가 변경되면 쿼리를 다시 실행하려는 경우와 같이 쿼리가 의존하는 모든 변수를 추가할 수도 있습니다.
const key =['user',name_variable]
useQuery(key, fetchData);
2 사용 옵션: 불필요한 쿼리를 피하기 위해 특정 조건이 충족된 후에만 쿼리가 실행되도록 하는 것이 매우 일반적입니다.
const key =['user']
useQuery(key, fetchData,
{
enabled:name_variable !== "" && name_variable.length > 3
);
3 선택 옵션: 반환된 데이터에 액세스할 수 있는 기능이며 렌더링하기 전에 클라이언트 측에서 데이터를 수정할 수 있습니다.
const query = useQuery(key, fetchData,
{
enabled: username.length > 3,
select: (data:User) => {
let newdata
if (data.user.isViewer){
newdata = {...data.user,OP:true}
return {user:newdata}
}
return data
}
}
)
선택 옵션을 사용하여 항목을 재정렬하고 데이터를 가져오지 않고 항목 배열을 필터링할 수도 있습니다.
const keyword = "a"
const query = useQuery(key, fetchData,
{
enabled: username.length > 3,
select: (data:User) => {
let newdata
if (keyword){
const followers = data.user.followers.edges.filter((item)=>{
return item.node.login.includes(keyword)
})
newdata = {...data.user,followers}
return {user:newdata}
}
return data
}
}
)
4 onError 및 onSuccess 부작용: 이 함수는 이러한 이벤트가 발생할 때 호출됩니다. 오류 코드가 401 또는 402인 경우 github 개인 액세스 토큰을 자동으로 무효화하고 onSuccess 내부에서 문제가 발생하지 않으면 로컬 저장소에 저장하는 데 사용했습니다.
const query = useQuery(key, fetchData,
{
enabled: username.length > 3,
select: (data:User) => {
let newdata
if (keyword){
const followers = data.user.followers.edges.filter((item)=>{
return item.node.login.includes(keyword)
})
newdata = {...data.user,followers}
return {user:newdata}
}
return data
},
onSuccess:(data:User)=>{
console.log("success")
//save token to local storage no issues with it
},
onError:(error:any)=>{
console.log("error = ",error.response)
if(error?.response?.status === "401" || error?.response?.status === "402"){
// invalidate my locally stored token to send me back to
// login screen,those codes mean tokenhas an issue
}
}
}
)
보너스 팁: useInfiniteQuery 후크
useInfiniteQuery 후크는 긴 데이터 목록의 페이지 매김을 처리하기 위한 것입니다.
예를 들어 graphql 쿼리에서 매우 긴 목록을 가질 수 있는 팔로워와 같은 필드에 매개 변수를 먼저 전달할 수 있습니다.
그래서 우리는 이렇게 페이지 매김을 소개합니다
const query = useInfiniteQuery(key, fetchData, {
enabled: username.length > 3,
onSuccess: (data: RootResponse) => {
console.log("success", data);
},
onError: (error: any) => {
console.log("error = ", error.response);
if (error?.response?.status === "401" || error?.response?.status === "402") {
// invalidate my locally stored token to send me back to
// login screen,those codes mean tokenhas an issue
}
},
getPreviousPageParam: (firstPage: Page) => {
return firstPage?.user?.followers?.pageInfo?.startCursor ?? null;
},
getNextPageParam: (lastPage: Page) => {
return lastPage?.user?.followers?.pageInfo?.endCursor ?? null;
},
});
console.log("test query === ",query.data)
추가 로드 버튼 추가
const pages = query?.data?.pages;
// console.log("followers === ",followers)
//@ts-ignore
const extras = pages[pages.length - 1].user?.followers;
const hasMore = extras?.pageInfo?.hasNextPage;
return (
<div className="w-full h-full ">
{!query.isFetchingNextPage && hasMore? (
<button
className="m-2 hover:text-purple-400 shadow-lg hover:shadow-purple"
onClick={() => {
query.fetchNextPage();
}}
>
--- load more ---
</button>
) : null}
{query.isFetchingNextPage ? (
<div className="w-full flex-center m-1 p-1">loading more...</div>
) : null}
</div>
)
기본적으로 반응 쿼리는 페이지 배열에 새 배열을 추가하고 중첩 루프를 사용하여 데이터를 출력해야 하는 페이지 배열로 데이터를 반환합니다.
<div className="h-fit w-full flex-center flex-wrap">
{pages?.map((page) => {
return page?.user?.followers?.edges?.map((item) => {
return (
<div className='w-[30%] h-14 p-3 m-2 border border-green-500 '>
user :{item.node.login}</div>
);
});
})}
</div>
또한 페이지 매김 getNextPageParam 및 getPreviousPageParam을 처리하기 위해 반응 쿼리에서 제공하는 부작용 함수에 유의하십시오.
이 경우 API가 pageInfo 필드 내부에 제공하는 종료 커서를 전달된 쿼리 함수에 값을 삽입합니다.
이 경우 변경하겠습니다.
const fetchData = async () => await graphQLClient.request(USER,{name:"tigawanna",
first:10,after:null
});
~ 안으로
const fetchData = async (deps: any) => {
const after = deps?.pageParam ? deps.pageParam : null;
return await graphQLClient.request(USER, {
name: "tigawanna",
first: 10,
after,
});
};
그리고 우리는 그것의 가치를 받을 deps에서 그것을 가져올 것입니다.
getNextPageParam: (lastPage: Page) => {
return lastPage?.user?.followers?.pageInfo?.endCursor ?? null;
},
이것은 잘 작동하지만 특정 키워드를 필터링하려는 경우 상황이 까다로워 데이터를 단일 배열로 변환하고 제공된 모든 키워드를 필터링하는 함수를 만들었습니다.
export const concatFollowerPages = (data: RootResponse, keyword: string) => {
let totalRepos = data.pages[0].user.followers.edges;
let i = 1;
for (i = 1; i < data.pages.length; i++) {
if (data?.pages) {
totalRepos = [...totalRepos, ...data.pages[i].user.followers.edges];
}
}
const filtered = totalRepos.filter((item) =>
item.node.login.toLowerCase().includes(keyword.toLowerCase())
);
const base = data.pages[data.pages.length -1].user;
const user = {
...base,
login: base.login,
followers: {
edges: filtered,
totalCount: base.followers.totalCount,
pageInfo: base.followers.pageInfo,
},
};
const final:RootResponse = {
pageParams: [...data.pageParams],
pages: [{ user: user }],
};
return final;
};
그런 다음 select 내부에서 호출합니다.
const query = useInfiniteQuery(key, fetchData, {
enabled: username.length > 3,
select:(data:RootResponse)=>{
return concatFollowerPages(data,"")
},
onSuccess: (data: RootResponse) => {
// console.log("success", data);
},
onError: (error: any) => {
console.log("error = ", error.response);
if (error?.response?.status === "401" || error?.response?.status === "402") {
// invalidate my locally stored token to send me back to
// login screen,those codes mean tokenhas an issue
}
},
getPreviousPageParam: (firstPage: Page) => {
return firstPage?.user?.followers?.pageInfo?.startCursor ?? null;
},
getNextPageParam: (lastPage: Page) => {
return lastPage?.user?.followers?.pageInfo?.endCursor ?? null;
},
});
전체 예제 코드의 경우 이해하기 쉽도록 모든 것을 자체 포함된 구성 요소에 압축했습니다.