이번 페이먼츠 미션이 우테코에서 진행한 미션들 중 1단계와 2단계의 gap이 가장 컸던 미션인 것 같아요.
1단계에서는 formik 라이브러리
를 뜯어보고 탐구하면서 많은 고민과 성장을 이룰 수 있었는데요!
라이브러리를 따와서 코딩을 하는 만큼 약간의 Legacy한 코드들이나 아쉬운 부분들이 있었던 것 같아요.
또한 고민과 이해가 부족한 저의 모습도 엿볼 수 있었어요.
추가적으로 커스텀 훅에 대한 고민
을 많이 진행하게 되었는데 피드백을 정리하는 과정에 있는 현재의 제가 볼 때에는 커스텀훅들이 단순히 로직을 꺼내기만 하고 재사용을 전혀 고려하지 않은 구조로 보이네요😅😅
이제라도 보이니 정말 다행입니다 ㅎㅎ;
그럼 2단계의 피드백을 살펴보러 가실까요?
Warning: Each child in a list should have a unique "key" prop.
{Object.values(storedList).map(({ cardName, values, id }) => (
<>
<Link to={PATH.EDIT_CARD_PAGE} state={{ cardName, values, id }}>
<CardPreview key={cardName} values={values} />
</Link>
<TextBox fontSize="14px">{cardName}</TextBox>
</>
))}
key값을 React.Fragment에 주었어야했는데 멍청하게 자식 컴포넌트에 주고 있었네요.
<React.Fragment key={id}> ...
이렇게 주어야합니다. onClick={async () => {
await deleteCard();
}}
👆 여기에 async를 쓰는 것이 맞을까요?
onClick={deleteCard}
👆 이렇게 바로 넘겨주어도 되지 않을까요?
input을 구현해야한다면 어떤 걸 사용할지 먼저 생각해봅시다.
🤔 실시간 validation이 필요없는 경우도 굳이 제어컴포넌트를 사용해야할까요?
<참고> 비제어 컴포넌트 만드는 방법
1. ref 사용하기
2. form으로 감싸서 onSubmit과 onChange 적극 활용하기
size라는 props로 small, big
값을 받아서 스타일을 분기해서 처리하는 방식을 고려해봅시다.const { initialField } = useFormSchema(initialCardSchema);
const [values, setValues] = useState(initialField);
const cardValues = useMemo(
() => ({ values, setValues, initialField }),
[values]
);
return (
<StyledApp>
<BackwardButton>카드 추가</BackwardButton>
<CardForm
cardFormSchema={cardFormSchema}
onSubmit={onSubmit}
onSubmitError={onSubmitError}
/>
</StyledApp>
<CardContext.Provider value={cardValues}>
...
</CardContext.Provider>
위의CardContext.Provider
를 children을 활용한 커스텀훅으로 분리해볼 수 있을 것 같아요.
import React, { createContext, useMemo, useState } from 'react';
import useFormSchema from '../hooks/useFormSchema';
import initialCardSchema from '../schema/cardSchema';
export const CardContext = createContext();
export const CardContextProvider = ({ children }) => {
const { initialField } = useFormSchema(initialCardSchema);
const [values, setValues] = useState(initialField);
const cardValues = useMemo(
() => ({ values, setValues, initialField }),
[values, initialField]
);
return (
<CardContext.Provider value={cardValues}>{children}</CardContext.Provider>
);
};
이런 느낌으로요!
color: ${(props) => props.color || '#04c09e'};
깔끔하지 못하네요ㅠㅠ
themeProvider를 사용해서 관리해봅시다!
아무리 페이지 단위의 성격을 가진 컴포넌트라고 해도 API 통신이 컴포넌트 내부에 포함된 것은 비추입니다.
useFetch라는 커스텀훅을 만들어봅시다!