Skip to content
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

[FE] 버튼 로딩 구현 및 이벤트 생성 페이지에 적용 #476

Merged
merged 16 commits into from
Aug 22, 2024

Conversation

Todari
Copy link
Contributor

@Todari Todari commented Aug 21, 2024

‼️#475 를 머지하고 머지해 주세요!!

475번 pr의 변경사항을 포함하고 있습니다

issue

구현 목적

  • User Test 결과 이벤트를 생성할 때, 비밀번호를 입력하고, 이벤트 생성 이벤트가 완료되는 텀 동안, 버튼을 다시 클릭하거나, 앱이 멈춘줄 아는 유저들이 많았습니다.
  • 이에 따라 요청 응답이 성공하기 전까지 button을 loading 상태로 변경하여 유저들에게 해당 요청이 전송됐고, 이를 기다리고 있다는 상태를 전달합니다.

구현 내용

1. loading animation을 위한 lottie animation

https://app.lottiefiles.com/animation/1e9dc066-f026-4fda-b4c5-522e29259397?panel=download

  • 로딩 상태를 나타내기 위한 애니메이션을 lottie 를 이용해 제작하였습니다.
  • lottie 애니메이션은 json 형태로 저장되어 고화질로 유연하게 적용할 수 있습니다.
  • svg의 벡터 기반이기 때문에 작은 파일 크기와 다양한 유연성으로 인한 장점이 있습니다.

2. Button loading variants

// FixedButton.tsx

// ~~

        <button
          css={fixedButtonStyle({variants, theme})}
          ref={ref}
          disabled={variants === 'loading' ? true : disabled}
          {...htmlProps}
        >
          {variants === 'loading' ? (
            <Lottie animationData={loadingAnimation} loop={true} style={{width: 240, height: 20}} />
          ) : (
            children
          )}
        </button>

// ~~
  • Button 컴포넌트와 FixedButton컴포넌트에 loading variants를 추가했습니다.
  • variant가 loading이면, 내부에 children 대신 lottie 애니메이션을 출력하고, disabled로 상태를 변경합니다.

3. SetEventPassword 페이지에 적용

// SetEventPasswordPage.tsx

const SetEventPasswordPage = () => {
  const {submitPassword, errorMessage, password, handleChange, canSubmit, isPostEventPending} =
    useSetEventPasswordPage();

  return (
      //~~ 

        <FixedButton variants={isPostEventPending ? 'loading' : 'primary'} disabled={!canSubmit}>
          행동 개시!
        </FixedButton>

      //~~ 
  );
};
// useSetEventPasswordPage.tsx
const {mutate: postEvent, isPending: isPostEventPending} = usePostEvent();

usePostEvent가 pending인 상태인 경우, FixedButton이 loading 상태가 되도록 구현하였습니다.

2024-08-22.4.10.11.mov

Trouble Shooting

  • pr을 올리자 마자 test가 터져버린것을 확인할 수 있었습니다.

image

  • lottie-web 라이브러리는 브라우저 환경을 필요로 하며, 일부 브라우저 관련 API(canvas, fillStyle 등)를 사용합니다. 그러나 Jest 테스트 환경에서 사용하는 jsdom은 브라우저의 일부 기능을 완전히 구현하지 않기 때문에, 이로 인해 fillStyle을 설정할 때 문제가 발생할 수 있습니다.

  • 따라서, 테스트 환경에서 Lottie 모듈을 사용하는 부분을 mocking하여, 실제로 Lottie 애니메이션을 렌더링하지 않도록 변경하여 테스트를 통과할 수 있었습니다.

// useError.test.tsx
jest.mock('lottie-react', () => () => <div>Lottie Mock</div>);

@Todari Todari added this to the lev3 milestone Aug 21, 2024
@Todari Todari requested review from pakxe, soi-ha and jinhokim98 August 21, 2024 19:25
@Todari Todari self-assigned this Aug 21, 2024
Copy link

Copy link

@Todari Todari linked an issue Aug 22, 2024 that may be closed by this pull request
2 tasks
Copy link
Contributor

@jinhokim98 jinhokim98 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

원래 로딩 애니메이션 제가 하려고 했는데 대신 맡아서 진행해줘서 고마워요!

@@ -60,6 +60,7 @@
"@emotion/react": "^11.11.4",
"@storybook/addon-webpack5-compiler-swc": "^1.0.5",
"@svgr/webpack": "^8.1.0",
"lottie-react": "^2.4.0",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이거는 dev dependency는 아닌 것 같은데 기술 검토를 맡을 필요가 있을 것 같아요. (물론 zustand, react-query 할 때는 하지 않기도 했죠)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

오호.. 확실히 lottie-react는 dev dependency는 아니라고 생각이 드네요! 프론트엔드 애니메이션을 구현하기 위해서 사용하는 라이브러리니까요! 기능 구현에 사용하기 때문에 dependency가 맞는 것 같습니다~!

Comment on lines +13 to +25
const animationSize = (size: ButtonSize) => {
switch (size) {
case 'small':
return {width: 30, height: 12};

case 'large':
return {width: 50, height: 20};

default:
return {width: 40, height: 16};
}
};

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

공 애니메이션 너무 좋다

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

인정합니다. 진짜 최고야.. 보는 내가 짜릿해..

{...htmlProps}
>
{variants === 'loading' ? (
<Lottie animationData={loadingAnimation} loop={true} style={animationSize(size)} />
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

loop true는 애니메이션을 계속 반복한다는 의미인가요?

@@ -10,6 +10,8 @@ import UnhandledErrorBoundary from '../../UnhandledErrorBoundary';
import {ErrorInfo, ErrorProvider} from './ErrorProvider';
import {useError} from './useError';

jest.mock('lottie-react', () => () => <div>Lottie Mock</div>);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

테스트 코드가 터지지 않도록 신경 써준 것까지 완벽;;;

@@ -15,7 +15,7 @@ const useSetEventPasswordPage = () => {
const [canSubmit, setCanSubmit] = useState(false);
const navigate = useNavigate();
const location = useLocation();
const {mutate: postEvent} = usePostEvent();
const {mutate: postEvent, isPending: isPostEventPending} = usePostEvent();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

isPending good~~~

Copy link
Contributor

@soi-ha soi-ha left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

저도 실제로 저희 서비스 qc를 하면서 이벤트가 생성되는 과정에서 기다리지 못하고 버튼을 두번 클릭한 적이 있는데요..
토다리가 이 부분을 신경써서 이번에 구현해줘서 너무 좋습니다! 최고에용!

@@ -60,6 +60,7 @@
"@emotion/react": "^11.11.4",
"@storybook/addon-webpack5-compiler-swc": "^1.0.5",
"@svgr/webpack": "^8.1.0",
"lottie-react": "^2.4.0",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

오호.. 확실히 lottie-react는 dev dependency는 아니라고 생각이 드네요! 프론트엔드 애니메이션을 구현하기 위해서 사용하는 라이브러리니까요! 기능 구현에 사용하기 때문에 dependency가 맞는 것 같습니다~!

Comment on lines +13 to +25
const animationSize = (size: ButtonSize) => {
switch (size) {
case 'small':
return {width: 30, height: 12};

case 'large':
return {width: 50, height: 20};

default:
return {width: 40, height: 16};
}
};

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

인정합니다. 진짜 최고야.. 보는 내가 짜릿해..

Copy link

@pakxe pakxe merged commit b9781cb into fe-dev Aug 22, 2024
2 checks passed
@pakxe pakxe deleted the feature/#474 branch August 22, 2024 15:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Status: ✅ Done
Development

Successfully merging this pull request may close these issues.

[FE] 버튼 로딩 구현 및 이벤트 생성 페이지에 적용
4 participants