React 및 GraphQL - 14를 사용하여 Reddit 클론 만들기
27280 단어 reactredditclonetypescriptgraphql
이 블로그 게시물은 원래 내 블로그 사이트에 게시되었으며 여기에서 찾을 수 있습니다.
middleware
라는 폴더를 만들고 isAuth.ts
파일을 추가하고 블로우 코드를 넣어봅시다.import { RedditDbContext } from "../types";
import { MiddlewareFn } from "type-graphql";
export const isAuth: MiddlewareFn<RedditDbContext> = ({ context }, next) => {
if (!context.req.session.userId) {
throw new Error("not authenticated");
}
return next();
};
그런 다음
post
리졸버에서 이 미들웨어를 사용할 수 있습니다. 이쪽@UseMiddleware
은type-graphql
@Mutation(() => Post)
@UseMiddleware(isAuth)
async createPost(
// ... remaining code
이제 프론트 엔드 앱으로 이동하여
Post
양식을 추가합니다. 페이지 폴더에 create-post.tsx
파일을 생성해 봅시다.이 코드를 추가해 보겠습니다.
const CreatePost: React.FC<{}> = ({}) => {
return (
<Wrapper variant="small">
<Formik
initialValues={{ title: "", text: "" }}
onSubmit={async (values) => {}}
>
{({ isSubmitting }) => (
<Form>
<InputField name="title" placeholder="title" label="Title" />
<Box mt={4}>
<InputField name="text" placeholder="text..." label="Body" />
</Box>
<Button
isLoading={isSubmitting}
mt={4}
type="submit"
colorScheme="teal"
>
Create Post
</Button>
</Form>
)}
</Formik>
</Wrapper>
);
};
export default CreatePost;
바디 필드용
textarea
이 있으면 더 좋습니다. InputField
구성 요소를 변경할 수 있습니다. prop
라고 불리는 textarea
를 받아 부울로 정의할 수 있습니다.... // InputFieldProps
textarea?: boolean
그런 다음
InputField
구성 요소에서 확인하십시오.
let InputOrTextarea = Input
if (textarea) {
InputOrTextarea = Textarea
}
...
<InputOrTextarea
{...props}
{...field}
id={field.name}
placeholder={props.placeholder}
/>
이제 돌연변이를 추가해야 합니다.
createPost.graphql
라는 파일을 만들고 아래 코드를 추가합니다. 그런 다음 실행yarn gen
mutation CreatePost($input: PostInput!) {
createPost(input: $input){
title
id
createdAt
creatorId
updatedAt
text
points
}
}
그런 다음
useCreatePostMutation
를 사용하고 게시물 생성 요청을 처리할 수 있습니다. 또한 이 게시물 작성 페이지에서 이 페이지에 NavBar를 추가해야 합니다. 이를 위한 공통 구성 요소를 만들어 보겠습니다. Layout.tsx
라는 구성 요소를 만들고 이 코드 블록을 추가합니다.import { NavBar } from "./NavBar";
import { Wrapper, WrapperVariant } from "./Wrapper";
interface LayoutProps {
// added WrapperVariant type
variant?: WrapperVariant;
}
export const Layout: React.FC<LayoutProps> = ({ children, variant }) => {
return (
<>
<NavBar />
<Wrapper variant={variant}>{children}</Wrapper>
</>
);
};
여기에서 Wrapper를 사용했기 때문입니다. 따라서 레이아웃에서 변형을 설정해야 합니다. 코드를 복제하지 않고 거기에 유형을 생성할 수 있습니다.
// Wrapper.tsx
export type WrapperVariant = "small" | "regular";
// change inside the Wrapper.tsx
interface WrapperProps {
variant?: WrapperVariant;
}
그런 다음 변형을 사용한 모든 곳에서 교체하십시오. 그런 다음
Wrapper
페이지에서 레이아웃으로 create-post.tsx
를 바꿀 수 있습니다.<Layout variant="small">...</Layout>
이제 이 navbar를 끈적하게 만들 수 있습니다. 아래 코드를 추가하여 끈끈하게 만듭니다.
// NavBar.tsx
<Flex zIndex={1} position="sticky" top={0} bg="tomato" p={4}>
...
이제 이 시점에서 사용자가 시스템에 로그인하지 않고 게시물을 작성하면 인증되지 않은 오류가 발생합니다.
onSubmit
함수에서 간단히 관리할 수 있습니다.
// create-post.tsx
onSubmit={async (values) => {
const { error } = await creatPost({ input: values });
if (error?.message.includes("not authenticated")) {
router.push("/login")
} else {
router.push("/");
}
}}
이 접근 방식의 문제는 사용자가 인증되었는지 여부에 대한 모든
graphql
쿼리를 확인해야 합니다. 이를 위해 전역 오류 처리기를 만들 수 있습니다. createUrqlClient.ts
에 아래 코드를 추가하고 exchanges
를 추가하십시오.import { pipe, tap } from "wonka";
const errorExchange: Exchange = ({ forward }) => (ops$) => {
return pipe(
forward(ops$),
tap(({ error }) => {
if (error?.message.includes("not authenticated")) {
Router.replace("/login");
}
})
);
};
// ...
// below in this file
exchanges: [
// ...
errorExchange,
ssrExchange,
fetchExchange,
];
사용자가 로그인 없이 작업을 시도하면 로그인 페이지로 이동합니다.
me
쿼리를 확인하여 사용자가 로그인했는지 확인하여 이를 개선할 수 있습니다. 이를 위해 우리는 후크를 생성할 수 있습니다. utils
폴더 안에 useIsAuth.ts
라는 파일을 추가하고 아래 코드를 추가합니다.import { useRouter } from "next/router";
import { useEffect } from "react";
import { useMeQuery } from "../generated/graphql";
export const useIsAuth = () => {
const [{ data, fetching }] = useMeQuery();
const router = useRouter();
useEffect(() => {
if (!fetching && !data?.me) {
router.replace("/login?next=" + router.pathname);
}
}, [fetching, data, router]);
};
여기에서 쿼리 매개변수로
router.pathname
를 추가합니다. 이것은 사용자가 이전에 있었던 이전 페이지로 다시 라우팅됩니다. create-post.tsx
페이지에서 이것을 사용합시다.const CreatePost: React.FC<{}> = ({}) => {
const router = useRouter();
useIsAuth();
// ...
그런 다음
login
페이지에서 다음 쿼리 매개변수로 로그인에 성공하면 해당 페이지로 이동합니다.// ...
// inside the onSubmit method
else if (response.data?.login.user) {
if (typeof router.query.next === "string") {
router.push(router.query.next);
} else {
router.push("/");
}
}
오류가 없으면 홈 페이지로 이동합니다.
// inside the onSubmit method
const { error } = await creatPost({ input: values });
if (!error) {
router.push("/");
}
또한 토큰도 쿼리 값으로 액세스할 수 있으므로
[token].tsx
페이지에서 토큰 전달 메커니즘을 수정할 수 있습니다. 따라서 해당 코드도 변경해 보겠습니다.
const ChangePassword: NextPage<{ token: string }> = () => {
...
// previously we took token as initial prop.
// const ChangePassword: NextPage<{ token: string }> = ({ token })
// ...
// get the token from the query parameter
const response = await changePassword({
newPassword: values.newPassword,
token:
typeof router.query.token === "string" ? router.query.token : "",
});
// then remove getInitialProps
// delete below code from the file
ChangePassword.getInitialProps = ({ query }) => {
return {
token: query.token as string,
};
};
getInitialProps
를 제거했으므로 Next.JS
이 페이지를 정적 페이지로 렌더링하도록 최적화합니다.읽어주셔서 감사합니다. 이와 관련하여 질문할 사항이 있으면 여기에 댓글을 남겨주세요. 또한 내 이해에 따라 이것을 썼습니다. 따라서 잘못된 점이 있으면 주저하지 말고 저를 수정하십시오. 정말 감사합니다.
오늘의 친구들을 위한 것입니다. 곧 봐요. 고맙습니다.
참조:
이 기사 시리즈는 . 이것은 놀라운 자습서이며 확인하는 것이 좋습니다.
기본 이미지credit
Reference
이 문제에 관하여(React 및 GraphQL - 14를 사용하여 Reddit 클론 만들기), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/rasikag/creating-a-reddit-clone-using-react-and-graphql-14-1bbf텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)