LV2 과제까지는 어찌어찌 하였다. react-router-dom, styled-components, redux를 사용해서 My Todo List를 만드는 것이였는데, 겨우 완성하였다. 그런데 LV3 과제는 뭔가 쉬울 것 같았지만 어려웠다. 특히나 Props에 대한 이해 부족이 큰 걸림돌이 되었던 거 같다.
(아래에 LV3과제에 대한 설명이 있다.)
정확히는 버튼을 만들 때부터 문제에 부딪혔는데, props활용해서 재사용하는 부분이 컨셉은 이해가 되면서도 어떻게 하는지, 잘 이해가 가지 않았다. 리팩토링 없이 구현한다면 사실 그렇게 어려운 것이 아니였는데, 그렇게 하면 이번 과제의 의미가 없기에 최대한 컴포넌트 재사용 방법을 사용하여 만들기 위해 이해하려 노력하였다. 그렇지만 버튼의 CSS속성을 props로 전달하는 부분 이해가 가지 않아서 진행할 수 없었다. 혼자서 고민해보다 기술매니저님의 예시코드를 받았다. 아래 코드가 그 예시 코드인데, 여기서 아래와 같은 시스템을 만드는 것은 고사하고 이해가 되지 않았는데, props와 ...restProps, styled-components에서 props 내려주는 코드부분 이해가 정확히 되지 않았다.
import React from "react";
import styled, { css } from "styled-components";
/*--------------------------------------------------------*
* Primitive Button
*--------------------------------------------------------*/
const PrimitiveButton = ({ children, rightSlot, ...restProps }) => {
return (
<StyledButton {...restProps}>
{rightSlot ? (
<ButtonInner>
<>{children}</>
<>{rightSlot}</>
</ButtonInner>
) : (
<>{children}</>
)}
</StyledButton>
);
};
/*--------------------------------------------------------*
* Primary Style
*--------------------------------------------------------*/
const PrimaryButton = (props) => {
return (
<PrimitiveButton
{...props}
bc="#55efc4"
color="#000000"
activeBc="#00b894"
/>
);
};
/*--------------------------------------------------------*
* Negative Style
*--------------------------------------------------------*/
const NegativeButton = (props) => {
return (
<PrimitiveButton
{...props}
bc="#fab1a0"
color="#d63031"
activeBc="#e17055"
/>
);
};
const Primary = PrimaryButton;
const Negative = NegativeButton;
const Button = { Negative, Primary };
export default Button;
const StyledButton = styled.button`
border: none;
cursor: pointer;
border-radius: 8px;
background-color: ${({ bc }) => bc};
color: ${({ color }) => color};
font-weight: ${({ fw }) => fw};
&:active {
background-color: ${({ activeBc }) => activeBc};
}
${({ size }) => {
switch (size) {
case "large":
return css`
height: 50px;
width: 200px;
`;
case "medium":
return css`
height: 45px;
width: 130px;
`;
case "small":
return css`
height: 40px;
width: 100px;
`;
default:
return css`
height: 40px;
width: 100px;
`;
}
}}
${({ outlined, bc }) => {
if (outlined) {
return css`
border: 3px solid ${bc};
background-color: #fff;
font-weight: 600;
&:active {
background-color: #eeeeee;
}
`;
}
}}
`;
const ButtonInner = styled.div`
display: flex;
align-items: center;
justify-content: center;
gap: 7px;
`;
-> 프로젝트 끝난 후 (2023년6월6일) 지금 다시 보았는데, 지금에서는
'왜 이해를 못 했을까? 아, 이게 어려운 것이 아니였구나.'
를 느꼈다. 저번 메인 프로젝트를 진행하면서 자연스레 이 부분들은 다 하게 되었다. Atomic system을 사용하려 Atoms, Molecules, Organisms, Templates, Modals 등으로 컴포넌트 재활용을 하였었다.
https://github.com/Maanna-zan/Maanna-zan_FE
에서 src/components를 체크해보면 된다.
우선 props부분 내려주고 받아주는 것 저번 프로젝트에서 연습 많이 하였고, ...restProps가 저기서 나온 이유는 PrimitiveButton 컴포넌트의 props 객체에서 명시적으로 선언되지 않은 모든 속성들을 배열로 받아오려고 JavaScript의 Rest parameter 문법을 사용하였다. 즉, PrimitiveButton 컴포넌트에서 명시적으로 선언되지 않은 속성들도 StyledButton 컴포넌트로 전달할 수 있게 되어, 컴포넌트 간의 속성 전달이 유연해지고 재사용성이 높아진다. 그리고 styled-components에서 props 내려주는 코드부분도 역시 저번 프로젝트때에 직접 사용하며 연습하였기에 익숙한 부분이 되었다.
Modal 부분 역시 많이 연습해보았는데, 다음에는 Modal의 Event Bubbling & Capturing에 대해서 공부하고 글을 써보아야 겠다.
취소
, 확인
이 있고, overlay를 클릭했을 때 모달이 닫히지 않는 형태닫기
버튼만 있고, overlay를 클릭했을 때 모달이 닫히는 형태on
시키는 버튼의 형태는 각각 달라야 합니다. (위에서 만든 버튼을 재사용하는 것도 좋아요.)styled-components
를 이용하여 구현하며, props를 적절하게 잘 활용하여 구현하세요.콤마 ,
가 찍히는 input저장
버튼을 눌렀을 때 {name: '아무 텍스트', price: "콤마가 없는 금액"}
을 alert
에 표시해보세요.select를 구현합니다.
overflow: hidden
을 적용하면 자식 컴포넌트가 부모 컴포넌트를 넘어갔을 때 가려지게 됩니다. 부모 컴포넌트에 hidden
속성이 있다고 하더라도 select는 가려지지 않아야 합니다.예시 사이트 : https://hh99-react-lv3.vercel.app/