Skip to content

Commit

Permalink
refactor: create-character
Browse files Browse the repository at this point in the history
  • Loading branch information
stakbucks committed Apr 6, 2024
1 parent 3c76271 commit 55bc7d8
Show file tree
Hide file tree
Showing 8 changed files with 49 additions and 37 deletions.
4 changes: 2 additions & 2 deletions src/components/create-character/hooks/useCreateCharacter.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
'use client';

import { useContext } from 'react';
import { CreateCharacterDispatchContext } from '@/context/create-character-provider';
import { CreateCharacterContext } from '@/context/create-character-provider';

export default function useCreateCharacter() {
const createCharacterDispatch = useContext(CreateCharacterDispatchContext);
const createCharacterDispatch = useContext(CreateCharacterContext);

if (createCharacterDispatch === null) throw new Error('CreateCharacter Provider를 감싸서 사용하세요');

Expand Down
7 changes: 3 additions & 4 deletions src/components/create-character/steps/select-color.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import React, { useContext, useState } from 'react';
import { CarouselDispatchContext } from '..';
import Header from '../header';
import Intro from '../intro';
import { CreateCharacterDispatchContext } from '@/context/create-character-provider';
import { useCreateCharacterContext } from '@/context/create-character-provider';
import CtaButton from '@/components/ui/cta-button';
import CheckCircle from '@/assets/icons/check-circle.svg';
import FixedBottomArea from '../fixed-bottom-area';
Expand All @@ -12,13 +11,13 @@ type ColorId = (typeof Colors)[number]['id'];

export default React.memo(function SelectColor() {
const [selected, setSelected] = useState<null | ColorId>(null);
const createCharacterDispatch = useContext(CreateCharacterDispatchContext);
const { setValue } = useCreateCharacterContext();
const carouselDispatch = useContext(CarouselDispatchContext);

const handleClick = () => {
if (selected === null) return;

createCharacterDispatch?.setValue('colorIdx', selected);
setValue('colorIdx', selected);
carouselDispatch?.handleNextClick();
};

Expand Down
4 changes: 2 additions & 2 deletions src/components/create-character/steps/select-item.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,16 @@ import Header from '../header';
import Intro from '../intro';
import React, { useState } from 'react';
import useCarousel from '../hooks/useCarousel';
import useCreateCharacter from '../hooks/useCreateCharacter';
import FixedBottomArea from '../fixed-bottom-area';
import { Items, NO_ITEM_IDX } from '@/constants/character-info';
import CtaButton from '@/components/ui/cta-button';
import { useCreateCharacterContext } from '@/context/create-character-provider';

type ItemId = (typeof Items)[number]['id'];

export default React.memo(function SelectItem() {
const [selected, setSelected] = useState<null | ItemId>(null);
const { setValue } = useCreateCharacter();
const { setValue } = useCreateCharacterContext();
const { handleNextClick } = useCarousel();

const handleClick = () => {
Expand Down
5 changes: 2 additions & 3 deletions src/components/create-character/steps/select-keywords.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@ import React, { useState } from 'react';
import CtaButton from '@/components/ui/cta-button';
import useCarousel from '../hooks/useCarousel';
import FixedBottomArea from '../fixed-bottom-area';
import useCreateCharacter from '../hooks/useCreateCharacter';
import { Keywords } from '@/constants/character-info';
import { useCreateCharacterContext } from '@/context/create-character-provider';

type KeywordId = (typeof Keywords)[number]['id'];

export default React.memo(function SelectKeywords() {
const { handleNextClick } = useCarousel();

const { setValue } = useCreateCharacter();
const { setValue } = useCreateCharacterContext();

const [selected, setSelected] = useState<Array<KeywordId>>([]);

Expand All @@ -28,7 +28,6 @@ export default React.memo(function SelectKeywords() {

const handleNextButtonClick = () => {
if (selected.length === 0) {
// TODO: 나중에 toast로 바꾸기
alert('키워드를 한 개 이상 선택해 주세요.');
return;
}
Expand Down
4 changes: 2 additions & 2 deletions src/components/create-character/steps/select-shape.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,15 @@ import React, { useState } from 'react';
import FixedBottomArea from '../fixed-bottom-area';
import Header from '../header';
import useCarousel from '../hooks/useCarousel';
import useCreateCharacter from '../hooks/useCreateCharacter';
import Intro from '../intro';
import { useCreateCharacterContext } from '@/context/create-character-provider';

type ShapeId = (typeof Shapes)[number]['id'];

export default React.memo(function SelectShape() {
const [selected, setSelected] = useState<null | ShapeId>(null);

const { setValue } = useCreateCharacter();
const { setValue } = useCreateCharacterContext();
const { handleNextClick } = useCarousel();

const handleSelect = (id: ShapeId) => {
Expand Down
4 changes: 3 additions & 1 deletion src/components/create-character/steps/set-name.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@ import Intro from '../intro';
import useCarousel from '../hooks/useCarousel';
import useCreateCharacter from '../hooks/useCreateCharacter';
import FixedBottomArea from '../fixed-bottom-area';
import { useCreateCharacterContext } from '@/context/create-character-provider';

const NAME_REGEX = /^[ㄱ-ㅎ|ㅏ-ㅣ|가-힣a-zA-Z\s]{1,8}$/;

export default React.memo(function SetName() {
const { setValue } = useCreateCharacter();
console.log('name rerender');
const { setValue } = useCreateCharacterContext();
const { handleNextClick } = useCarousel();
const nameRef = useRef<HTMLInputElement | null>(null);

Expand Down
21 changes: 10 additions & 11 deletions src/components/create-character/steps/show-result.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,11 @@
import HomeBg from '@/assets/images/homeBg.jpg';
import CtaButton from '@/components/ui/cta-button';
import { Keywords, NO_ITEM_IDX } from '@/constants/character-info';
import { CreateCharacterValues, CreateCharacterValuesContext } from '@/context/create-character-provider';
import {
CreateCharacterContext,
CreateCharacterValues,
useCreateCharacterContext,
} from '@/context/create-character-provider';
import { sendGTMEvent } from '@next/third-parties/google';
import { getCookie, setCookie } from 'cookies-next';
import Image from 'next/image';
Expand Down Expand Up @@ -35,15 +39,10 @@ export default function ShowResult() {
const searchParams = useSearchParams();
const step = searchParams.get('step');

const createCharacterValues = useContext(CreateCharacterValuesContext);
const { getValues } = useCreateCharacterContext();
const values = getValues();

if (createCharacterValues === null) {
alert('처음부터 하세요.');
router.push('/');
throw new Error('');
}

const { colorIdx, shapeIdx, name, keywords, itemIdx } = createCharacterValues;
const { colorIdx, shapeIdx, name, keywords, itemIdx } = values;
const characterImg = `https://kr.object.ncloudstorage.com/kekeche-character/character/${shapeIdx}/0/${colorIdx}.webp`;
const itemImg =
itemIdx !== NO_ITEM_IDX ? `https://kr.object.ncloudstorage.com/kekeche-character/item/${itemIdx}.webp` : null;
Expand All @@ -54,14 +53,14 @@ export default function ShowResult() {
const handleNextBtnClick = async () => {
try {
// 캐릭터 생성 api...
const { id } = await createCharacter(createCharacterValues, `${getCookie('accessToken')}`);
const { id } = await createCharacter(values, `${getCookie('accessToken')}`);
router.push(`/character/${id}`);
router.refresh();
sendGTMEvent({ event: 'createCharacter' });
} catch (err) {
// 로그인 안 한 사람->'앗' 페이지
console.log(err);
setCookie('create-character', JSON.stringify(createCharacterValues));
setCookie('create-character', JSON.stringify(values));
handleNextClick();
}
};
Expand Down
37 changes: 25 additions & 12 deletions src/context/create-character-provider.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
'use client';

import { createContext, useCallback, useMemo, useRef, useState } from 'react';
import { createContext, useCallback, useContext, useMemo, useRef } from 'react';

type Props = {
children: React.ReactNode;
Expand All @@ -15,12 +15,13 @@ export interface CreateCharacterValues {
itemIdx?: number | null;
}

interface CreateCharacterDispatch {
interface CreateCharacterContext {
setValue<T extends keyof CreateCharacterValues>(target: T, value: CreateCharacterValues[T]): void;
getValue<T extends keyof CreateCharacterValues>(target: T): CreateCharacterValues[T];
getValues(): CreateCharacterValues;
}

export const CreateCharacterValuesContext = createContext<null | CreateCharacterValues>(null);
export const CreateCharacterDispatchContext = createContext<null | CreateCharacterDispatch>(null);
export const CreateCharacterContext = createContext<null | CreateCharacterContext>(null);

export default function CreateCharacterProvider({ children }: Props) {
const createCharacterValues = useRef<CreateCharacterValues>({});
Expand All @@ -35,13 +36,25 @@ export default function CreateCharacterProvider({ children }: Props) {
[],
);

const memoizedSetValue = useMemo(() => ({ setValue }), [setValue]);
const getValue = useCallback(<T extends keyof CreateCharacterValues>(target: T) => {
return createCharacterValues.current[target];
}, []);

return (
<CreateCharacterValuesContext.Provider value={createCharacterValues.current}>
<CreateCharacterDispatchContext.Provider value={memoizedSetValue}>
{children}
</CreateCharacterDispatchContext.Provider>
</CreateCharacterValuesContext.Provider>
);
const getValues = useCallback(() => {
return createCharacterValues.current;
}, []);

const memoizedValue = useMemo(() => ({ setValue, getValue, getValues }), [getValue, getValues, setValue]);

return <CreateCharacterContext.Provider value={memoizedValue}>{children}</CreateCharacterContext.Provider>;
}

export function useCreateCharacterContext() {
const createCharacterContext = useContext(CreateCharacterContext);

if (createCharacterContext === null) {
throw new Error('CreateCharacterContext를 감싸서 사용하세요.');
}

return createCharacterContext;
}

0 comments on commit 55bc7d8

Please sign in to comment.