-
Notifications
You must be signed in to change notification settings - Fork 66
[클린코드 리액트 3기 이정수] 페이먼츠 미션 Step1 #150
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: dolilu
Are you sure you want to change the base?
Changes from 1 commit
2586649
2e3567a
336d9c9
c3d8f46
43fd884
5689c6d
0dec376
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| import React, {useContext} from "react" | ||
| import CardContext from "../context/CardContext.tsx"; | ||
| import {CardType} from "../type/CardType.ts"; | ||
| import {useStepper} from "../context/StepperContext.tsx"; | ||
| import {AddCardCompleteProps} from "../interface/AddCardCompleteProps.ts"; | ||
|
|
||
| const AddCardComplete: React.FC<AddCardCompleteProps> = ({cardName, cardNumber, name, cardExpireDate, cardAlias}) => { | ||
| const {modifyCard} = useContext(CardContext) | ||
| const {setCurrentStep} = useStepper() | ||
|
|
||
| const handleClick = () => { | ||
| const card: CardType = {cardName, cardNumber, name, cardExpireDate, cardAlias} | ||
| modifyCard(card) | ||
| setCurrentStep("CardList") | ||
| } | ||
|
|
||
| return ( | ||
| <div className="button-box"> | ||
| <span className="button-text" onClick={handleClick}>다음</span> | ||
| </div> | ||
| ) | ||
| } | ||
|
|
||
| export default AddCardComplete |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| import React from "react"; | ||
| import {useStepper} from "../context/StepperContext.tsx"; | ||
|
|
||
| export interface DivInputProps { | ||
| className: string | ||
| step?: string | ||
| value?: string | ||
| } | ||
|
|
||
| const DivButton: React.FC<DivInputProps> = ({className, step, value}) => { | ||
| const {setCurrentStep} = useStepper() | ||
| const handleClick = () => { | ||
| if (step) { | ||
| setCurrentStep(step) | ||
| } | ||
| } | ||
|
|
||
| return ( | ||
| <> | ||
| <div | ||
| className={className} | ||
| onClick={handleClick} | ||
| > | ||
| {value} | ||
| </div> | ||
| </> | ||
| ) | ||
| } | ||
|
|
||
| export default DivButton |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,36 @@ | ||
| import React from 'react'; | ||
| import {useStepper} from "../context/StepperContext.tsx"; | ||
| import IntrinsicElements = React.JSX.IntrinsicElements; | ||
|
|
||
| export interface HeaderButtonProps { | ||
| tag: string | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. a: polymorphic하게 컴포넌트 구현해주셨네요 💯 정수님이 구현하신 것처럼 아토믹 컴포넌트에서 tag를 polymorphic하게 전달받으면 스타일은 재사용하면서 다른 html 요소의 기능을 사용할 수 있어 확장성이 개선됩니다. |
||
| className: string | ||
| step?: string | ||
| value?: string | ||
| } | ||
|
|
||
|
|
||
| const HeaderButton: React.FC<HeaderButtonProps> = ({tag, className, step, value}) => { | ||
| const {setCurrentStep} = useStepper() | ||
| const handleClick = () => { | ||
| if (step) { | ||
| setCurrentStep(step) | ||
| } | ||
| } | ||
|
|
||
| const Tag = tag as keyof IntrinsicElements; | ||
|
|
||
| return ( | ||
| <> | ||
| <Tag | ||
| className={className} | ||
| onClick={handleClick} | ||
| > | ||
| {value} | ||
| </Tag> | ||
| </> | ||
| ) | ||
| } | ||
|
||
|
|
||
|
|
||
| export default HeaderButton; | ||
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -4,11 +4,13 @@ import {CardType} from "../type/CardType.ts"; | |
| interface CardContextType { | ||
| cards: CardType[] | ||
| addCard: (newCard: CardType) => void | ||
| modifyCard: (newCard: CardType) => void | ||
| } | ||
|
|
||
| const CardContext = createContext<CardContextType>({ | ||
| cards: [], | ||
| addCard: () => {} | ||
| addCard: () => {}, | ||
| modifyCard: () => {} | ||
| }); | ||
|
|
||
| export const CardProvider: React.FC<{ children: React.ReactNode}> = ({ children }) => { | ||
|
|
@@ -18,8 +20,15 @@ export const CardProvider: React.FC<{ children: React.ReactNode}> = ({ children | |
| setCards(prevCards => [...prevCards, newCard]); | ||
| } | ||
|
|
||
| const modifyCard = (newCard: CardType) => { | ||
| setCards(prevCards => { | ||
| const cards = prevCards.slice(0, prevCards.length -1); | ||
| return [...cards, newCard]; | ||
| }) | ||
| } | ||
|
Comment on lines
+27
to
+32
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. c: 지금은 잘 동작하지만 추후 선택한 카드의 정보를 변경하는 경우 로직이 많이 변경되어 다른 컴포넌트에 수정이 전파될 것 같네요.
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 다른 부분은 다 수정했는데, 이 부분은 힌트를 좀 더 부탁드립니다. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 마지막 요소만 수정가능한 것 같아 특정 카드를 선택해 정보를 수정하는 경우 id를 통한 비교가 이루어져야 할 것 같다는 의미였습니다. 지금은 잘 동작하니 넘어가셔도 좋습니다. |
||
|
|
||
| return ( | ||
| <CardContext.Provider value={{ cards, addCard }}> | ||
| <CardContext.Provider value={{ cards, addCard, modifyCard }}> | ||
| {children} | ||
| </CardContext.Provider> | ||
| ) | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| import React, {createContext, useContext, useState} from 'react' | ||
|
|
||
| interface StepperContextType { | ||
| step: string | ||
| setCurrentStep: (step: string) => void | ||
| } | ||
|
|
||
| const StepperContext = createContext<StepperContextType>({ | ||
| step: "/", | ||
| setCurrentStep: () => {} | ||
| }); | ||
|
|
||
| export const StepperProvider: React.FC<{ children: React.ReactNode}> = ({ children }) => { | ||
| const [step, setStep] = useState<string>("/") | ||
|
|
||
| const setCurrentStep = (step: string) => { | ||
| setStep(step) | ||
| } | ||
|
|
||
| return ( | ||
| <StepperContext.Provider value={{ step, setCurrentStep }}> | ||
| {children} | ||
| </StepperContext.Provider> | ||
| ) | ||
| } | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. a: Context API 사용해 stepper 잘 구현해주셨네요! 💯 |
||
|
|
||
| export const useStepper = () => useContext(StepperContext); | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
r: 카드 입력 폼은 경로처럼 '/'로, 다른 단계는 직접 명시하셨네요. 랜딩 페이지의 느낌으로 '/'를 사용하신 거라 생각되는데, 다른 step과 마찬가지로 적어주는 것이 명시적이고, 또 이후 카드 등록 플로우 요구사항 변경 시 유연하게 대응할 수 있을 것 같습니다.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
수정했습니다.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
변경 하였습니다.