-
Notifications
You must be signed in to change notification settings - Fork 4
[FEAT] 호스트 페이지 렌더링 최적화 #168
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
Merged
Merged
Changes from all commits
Commits
Show all changes
9 commits
Select commit
Hold shift + click to select a range
4c5cc8a
chore: 리액트 훅 폼 설정
jsk3342 1a265bb
feat: 방송 제목 필드 분리 및 최적화
jsk3342 f6601fe
chore: 폼 스타일 분리
jsk3342 a7a16b8
feat: 폼 인풋 분리 및 훅폼 적용
jsk3342 d20e15d
fix: 변경된 api 타입 변경
jsk3342 bc073ed
feat: 훅폼 적용으로 렌더링 최적화
jsk3342 4dce3b0
fix: 한글 입력 시 두 번 입력되는 오류 개선
jsk3342 6093bb8
fix: 호스트 폼 타입 폴더로 관리
jsk3342 0f1c5a5
fix: 타입 에러 수정
jsk3342 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| import { Controller, useFormContext } from 'react-hook-form'; | ||
| import { FormCell, Input, Label } from './style'; | ||
| import { FormValues } from '@type/hostInfo'; | ||
|
|
||
| export default function CategoryField() { | ||
| const { control } = useFormContext<FormValues>(); | ||
|
|
||
| return ( | ||
| <FormCell> | ||
| <Label>카테고리</Label> | ||
| <Controller | ||
| name="category" | ||
| control={control} | ||
| render={({ field }) => <Input {...field} type="text" placeholder="카테고리 검색" />} | ||
| /> | ||
| </FormCell> | ||
| ); | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| import { Controller, useFormContext } from 'react-hook-form'; | ||
| import { FormCell, Input, Label, Required } from './style'; | ||
| import { FormValues } from '@type/hostInfo'; | ||
|
|
||
| export default function HostNameField() { | ||
| const { control } = useFormContext<FormValues>(); | ||
|
|
||
| return ( | ||
| <FormCell> | ||
| <Label> | ||
| 호스트 이름<Required>*</Required> | ||
| </Label> | ||
| <Controller | ||
| name="hostName" | ||
| control={control} | ||
| render={({ field }) => ( | ||
| <Input {...field} type="text" placeholder="호스트 이름을 입력해 주세요." maxLength={100} /> | ||
| )} | ||
| /> | ||
| </FormCell> | ||
| ); | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,84 @@ | ||
| import { useCallback, useRef } from 'react'; | ||
| import { useFormContext, useWatch } from 'react-hook-form'; | ||
| import { FormValues } from '@type/hostInfo'; | ||
| import { convertToBase64 } from '@utils/convertToBase64'; | ||
| import { | ||
| FileInput, | ||
| FileInputLabel, | ||
| FormCell, | ||
| ImageActionButtons, | ||
| ImageButton, | ||
| ImageContainer, | ||
| ImageUpload, | ||
| Label, | ||
| PlaceholderImage, | ||
| PreviewImage, | ||
| UploadIcon, | ||
| UploadText | ||
| } from './style'; | ||
|
|
||
| export default function ImageField() { | ||
| const fileInputRef = useRef<HTMLInputElement>(null); | ||
| const { control, setValue } = useFormContext<FormValues>(); | ||
| const previewImage = useWatch({ | ||
| control, | ||
| name: 'previewImage', | ||
| defaultValue: null | ||
| }); | ||
|
|
||
| const handleImageChange = useCallback( | ||
| async (e: React.ChangeEvent<HTMLInputElement>): Promise<void> => { | ||
| const files = e.target.files; | ||
| if (!files) return; | ||
|
|
||
| const base64 = await convertToBase64(files[0]); | ||
| setValue('previewImage', base64); | ||
| }, | ||
| [setValue] | ||
| ); | ||
|
|
||
| const handleImageDelete = useCallback(() => { | ||
| setValue('previewImage', null); | ||
| if (fileInputRef.current) { | ||
| fileInputRef.current.value = ''; | ||
| } | ||
| }, [setValue]); | ||
|
|
||
| return ( | ||
| <FormCell> | ||
| <Label>미리보기 이미지</Label> | ||
| <ImageUpload> | ||
| {previewImage ? ( | ||
| <ImageContainer> | ||
| <PreviewImage src={previewImage} alt="미리보기 이미지" /> | ||
| <ImageActionButtons> | ||
| <ImageButton as="label" htmlFor="preview-image-input"> | ||
| 수정 | ||
| </ImageButton> | ||
| <ImageButton onClick={handleImageDelete} type="button"> | ||
| 삭제 | ||
| </ImageButton> | ||
| </ImageActionButtons> | ||
| </ImageContainer> | ||
| ) : ( | ||
| <FileInputLabel htmlFor="preview-image-input"> | ||
| <PlaceholderImage> | ||
| <UploadIcon xmlns="http://www.w3.org/2000/svg" viewBox="0 0 14 14" fill="none"> | ||
| <path d="M1 7H13" stroke="#AEB4C2" strokeWidth="1.5" strokeLinecap="round" /> | ||
| <path d="M7 1L7 13" stroke="#AEB4C2" strokeWidth="1.5" strokeLinecap="round" /> | ||
| </UploadIcon> | ||
| <UploadText>업로드 (1280x720)</UploadText> | ||
| </PlaceholderImage> | ||
| </FileInputLabel> | ||
| )} | ||
| <FileInput | ||
| ref={fileInputRef} | ||
| id="preview-image-input" | ||
| type="file" | ||
| accept="image/*" | ||
| onChange={handleImageChange} | ||
| /> | ||
| </ImageUpload> | ||
| </FormCell> | ||
| ); | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| import { Controller, useFormContext } from 'react-hook-form'; | ||
| import { Bold, CharCount, FormCell, Input, Label, Required } from './style'; | ||
| import { FormValues } from '@type/hostInfo'; | ||
|
|
||
| export default function LiveTitleField() { | ||
| const { control } = useFormContext<FormValues>(); | ||
|
|
||
| return ( | ||
| <FormCell> | ||
| <Label> | ||
| 방송 제목<Required>*</Required> | ||
| </Label> | ||
| <Controller | ||
| name="liveTitle" | ||
| control={control} | ||
| render={({ field }) => ( | ||
| <> | ||
| <Input {...field} type="text" placeholder="방송 제목을 입력해주세요." maxLength={100} /> | ||
| <CharCount> | ||
| <Bold>{field.value?.length || 0}</Bold>/100 | ||
| </CharCount> | ||
| </> | ||
| )} | ||
| /> | ||
| </FormCell> | ||
| ); | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| import { Controller, useFormContext } from 'react-hook-form'; | ||
| import { FormValues } from '@type/hostInfo'; | ||
| import { FormCell, Input, Label } from './style'; | ||
|
|
||
| export default function NoticeField() { | ||
| const { control } = useFormContext<FormValues>(); | ||
|
|
||
| return ( | ||
| <FormCell> | ||
| <Label>공지</Label> | ||
| <Controller | ||
| name="notice" | ||
| control={control} | ||
| render={({ field }) => <Input {...field} type="text" placeholder="공지 추가하기" />} | ||
| /> | ||
| </FormCell> | ||
| ); | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,81 @@ | ||
| import { Controller, useFormContext } from 'react-hook-form'; | ||
| import { FormValues } from '@type/hostInfo'; | ||
| import { | ||
| Button, | ||
| Flex, | ||
| FormCell, | ||
| Input, | ||
| Label, | ||
| RemoveButton, | ||
| TagChipContainer, | ||
| TagContainer, | ||
| UploadText | ||
| } from './style'; | ||
| import { KeyboardEvent } from 'react'; | ||
|
|
||
| export default function TagField() { | ||
| const { control, setValue, getValues } = useFormContext<FormValues>(); | ||
|
|
||
| const onKeyDown = (e: KeyboardEvent<HTMLInputElement>) => { | ||
| if (e.key === 'Enter' && !e.nativeEvent.isComposing) { | ||
| e.preventDefault(); | ||
| onAddTag(); | ||
| } | ||
| }; | ||
|
|
||
| const onAddTag = () => { | ||
| const currentTag = getValues('tag').trim(); | ||
| if (currentTag) { | ||
| const currentTags = getValues('tags'); | ||
| setValue('tags', [...currentTags, currentTag]); | ||
| setValue('tag', ''); | ||
| } | ||
| }; | ||
|
|
||
| const onRemoveTag = (indexToRemove: number) => { | ||
| const currentTags = getValues('tags'); | ||
| setValue( | ||
| 'tags', | ||
| currentTags.filter((_: string, index: number) => index !== indexToRemove) | ||
| ); | ||
| }; | ||
|
|
||
| return ( | ||
| <FormCell> | ||
| <Label>태그</Label> | ||
| <Flex> | ||
| <Controller | ||
| name="tag" | ||
| control={control} | ||
| render={({ field }) => <Input {...field} type="text" placeholder="태그 추가하기" onKeyDown={onKeyDown} />} | ||
| /> | ||
| <Button type="button" onClick={onAddTag}> | ||
| 추가 | ||
| </Button> | ||
| </Flex> | ||
| <Controller | ||
| name="tags" | ||
| control={control} | ||
| render={({ field }) => ( | ||
| <>{field.value.length > 0 && <TagList tags={field.value} onRemoveTag={onRemoveTag} />}</> | ||
| )} | ||
| /> | ||
| <UploadText>공백 및 특수 문자 없이 15자까지 입력할 수 있습니다.</UploadText> | ||
| </FormCell> | ||
| ); | ||
| } | ||
|
|
||
| const TagChip = ({ tag, onRemove }: { tag: string; onRemove: () => void }) => ( | ||
| <TagChipContainer> | ||
| {tag} | ||
| <RemoveButton onClick={onRemove}>×</RemoveButton> | ||
| </TagChipContainer> | ||
| ); | ||
|
|
||
| const TagList = ({ tags, onRemoveTag }: { tags: string[]; onRemoveTag: (index: number) => void }) => ( | ||
| <TagContainer> | ||
| {tags.map((tag, index) => ( | ||
| <TagChip key={tag + index} tag={tag} onRemove={() => onRemoveTag(index)} /> | ||
| ))} | ||
| </TagContainer> | ||
| ); | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| export { default as LiveTitleField } from './LiveTitleField'; | ||
| export { default as CategoryField } from './CategoryField'; | ||
| export { default as TagField } from './TagField'; | ||
| export { default as NoticeField } from './NoticeField'; | ||
| export { default as ImageField } from './ImageField'; | ||
| export { default as HostNameField } from './HostNameField'; |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
setValue가 2개인데 의도한 것인가요?
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.
tag, tags가 있는데 tag에서 엔터를 치면 tags 배열에 들어가고 tag는 다른 인풋을 받기 위해 빈스트링으로 설정합니다.