[노현지] Sprint8#77
Hidden character warning
Conversation
|
스프리트 미션 하시느라 수고 많으셨어요. |
| import { Product, Comment } from "../utils/types"; | ||
|
|
||
| const instance = axios.create({ | ||
| baseURL: "https://panda-market-api.vercel.app", |
There was a problem hiding this comment.
base URL은 환경 변수에 저장하시는게 좋습니다!
환경 변수(Environment Variable):
process.env에 내장되며 앱이 실행될 때 적용할 수 있는 값입니다!
다음과 같이 적용할 수 있습니다:
// .env.development
REACT_APP_BASE_URL="http://localhost:3000"
// .env.production
REACT_APP_BASE_URL="http://myapi.com"
// 사용시
<a href={`${process.env.REACT_APP_BASE_URL}/myroute`}>URL</a>
왜 환경 변수에 저장해야 하나요?
개발(dev), 테스트(test), 실제 사용(prod) 등 다양한 환경에서 앱을 운영하게 되는 경우, 각 환경에 따라 다른 base URL을 사용해야 할 수 있습니다. 만약 코드 내에 하드코딩되어 있다면, 각 환경에 맞춰 앱을 배포할 때마다 코드를 변경해야 하며, 이는 매우 번거로운 작업이 됩니다. 하지만, 환경 변수를 .env.production, .env.development, .env.test와 같이 설정해두었다면, 코드에서는 단지 다음과 같이 적용하기만 하면 됩니다.
const apiUrl = `${process.env.REACT_APP_BASE_URL}/api`;
이러한 방식으로 환경 변수를 사용하면, 배포 환경에 따라 쉽게 URL을 변경할 수 있으며, 코드의 가독성과 유지보수성도 개선됩니다.
실제 코드 응용과 관련해서는 다음 한글 아티클을 참고해보세요! => 보러가기
| export async function getItemComments( | ||
| productId: string, | ||
| { cursor = 0 }: { cursor: number } | ||
| ): Promise<GetCommentsResponse> { |
| pageSize: string; | ||
| order: string; | ||
| }): Promise<GetItemsResponse> { | ||
| const query = new URLSearchParams({ page, pageSize, orderBy: order }); |
| interface PrimaryButtonProps { | ||
| children: React.ReactNode; | ||
| className?: string; | ||
| onClick?: React.MouseEventHandler<HTMLButtonElement>; | ||
| disabled?: boolean; | ||
| type?: "button" | "submit" | "reset"; | ||
| } | ||
|
|
||
| function PrimaryButton({ | ||
| children, | ||
| className = "", | ||
| onClick = () => {}, | ||
| disabled = false, | ||
| type = "submit", | ||
| }: PrimaryButtonProps) { | ||
| const buttonClass = `${styles.button} ${className}`; | ||
| return ( | ||
| <button | ||
| type={type} | ||
| className={buttonClass} | ||
| onClick={onClick} | ||
| disabled={disabled} | ||
| > | ||
| {children} | ||
| </button> | ||
| ); | ||
| } |
There was a problem hiding this comment.
다음과 같이 작성해볼 수도 있을 것 같아요 !
| interface PrimaryButtonProps { | |
| children: React.ReactNode; | |
| className?: string; | |
| onClick?: React.MouseEventHandler<HTMLButtonElement>; | |
| disabled?: boolean; | |
| type?: "button" | "submit" | "reset"; | |
| } | |
| function PrimaryButton({ | |
| children, | |
| className = "", | |
| onClick = () => {}, | |
| disabled = false, | |
| type = "submit", | |
| }: PrimaryButtonProps) { | |
| const buttonClass = `${styles.button} ${className}`; | |
| return ( | |
| <button | |
| type={type} | |
| className={buttonClass} | |
| onClick={onClick} | |
| disabled={disabled} | |
| > | |
| {children} | |
| </button> | |
| ); | |
| } | |
| interface PrimaryButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> { | |
| className?: string; | |
| children?: React.ReactNode; | |
| } | |
| function PrimaryButton({ | |
| children, | |
| className = "", | |
| }: PrimaryButtonProps) { | |
| const buttonClass = `${styles.button} ${className}`; | |
| return ( | |
| <button | |
| type={type} | |
| className={buttonClass} | |
| {...rest} | |
| > | |
| {children} | |
| </button> | |
| ); | |
| } |
ButtonHTMLAttributes<HTMLButtonElement> 타입으로 확장하면 컴파일 단계에서 버튼의 속성들만 받을 수 있도록 할 수 있습니다 😊
| const PAGE_ARRAY = [1, 2, 3, 4, 5]; | ||
| const PAGE_CHUNK_SIZE = 5; | ||
|
|
||
| type Order = "recent" | "favorite"; |
There was a problem hiding this comment.
굿굿 ! string이 아닌 유니온 타입으로 잘 설정하셨네요:
(이어서)
| order = "", | ||
| }: { | ||
| page: string; | ||
| pageSize: string; | ||
| order: string; |
There was a problem hiding this comment.
(이어서) 여기도 타입을 "recent" | "favorite"로 하시면 어떨까요?
| order = "", | |
| }: { | |
| page: string; | |
| pageSize: string; | |
| order: string; | |
| order = "", | |
| }: { | |
| page: string; | |
| pageSize: string; | |
| order: "recent" | "favorite"; |
그리고 "recent" | "favorite"는 getItems 함에 필요한 타입이므로 타입 선언을 해당 파일에서 선언하셔도 될 것 같습니다 =)
| }; | ||
|
|
||
| const handleFileChange = (event) => { | ||
| const handleFileChange = (event: ChangeEvent<HTMLInputElement>) => { |
|
수고하셨습니다 현지님 ! 이번 미션 정말 잘 수행하셨습니다 😊😊 미션 수행하시느라 정말 고생 많으셨습니다 ! (참고) 이전 피드백:
예를 들어서 다음과 같은 컴포넌트를 만들어볼 수 있을 것 같아요: import styles from "./Button.module.css";
function Button({
children,
variant = "primary",
icon,
// onClick = () => {},
className = "",
// disabled = false,
...rest
}) {
return (
<button
className={`${styles.button} ${styles[variant]} ${className}`}
// onClick={onClick}
// disabled={disabled} 해당 내용들은 `rest`에 자동 등재
{...rest}
>
{icon && <img src={icon} alt="" className={styles.icon} />}
{children}
</button>
);
}
export default Button; |
요구사항
기본
심화
주요 변경사항
멘토에게