Skip to content

Commit 4a2365f

Browse files
committed
docs: translate default-props
1 parent d9a433d commit 4a2365f

File tree

2 files changed

+208
-0
lines changed

2 files changed

+208
-0
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
.DS_Store

README.md

+207
Original file line numberDiff line numberDiff line change
@@ -758,3 +758,210 @@ class Comp extends React.PureComponent<Props, State> {
758758
[TypeScript Playground에서 확인해 보기](https://www.typescriptlang.org/play/?jsx=2#code/JYWwDg9gTgLgBAJQKYEMDG8BmUIjgcilQ3wFgAoUSWOYAZwFEBHAVxQBs5tcD2IATFHQAWAOnpJWHMuQowAnmCRwAwizoxcANQ4tlAXjgoAdvIDcFYMZhIomdMoAKOMHTgBvCnDhgXAQQAuVXVNEB12PQtyAF9La1t7NGUAESRMKyR+AGUYFBsPLzgIGGFbHLykADFgJHZ+II0oKwBzKNjyBSU4cvzDVPTjTJ7lADJEJBgWKGMAFUUkAB5OpAhMOBgoEzpMaBBnCFcZiGGAPijMFmMMYAhjdc3jbd39w+PcmwAKXwO6IJe6ACUBXI3iIk2mwO83joKAAbpkXoEfC46KJvmA-AAaOAAehxcBh8K40DgICQIAgwAAXnkbsZCt5+LZgPDsu8kEF0aj0X5CtE2hQ0OwhG4VLgwHAkAAPGzGfhuZDoGCiRxTJBi8C3JDWBb-bGnSFwNC3RosDDQL4ov4ooGeEFQugsJRQS0-AFRKHrYT0UQaCpwQx2z3eYqlKDDaq1epwABEAEYAEwAZhjmIZUNEmY2Wx2UD2KKOw1drgB6f5fMKfpgwDQcGaE1STVZEZw+Z+xd+cD1BPZQWGtvTwDWH3ozDY7A7aP82KrSF9cIR-gBQLBUzuxhY7HYHqhq4h2ceubbryLXPdFZiQA)
759759

760760
<!--END-SECTION:class-components-->
761+
762+
<!--START-SECTION:default-props-->
763+
764+
#### `defaultProps`가 필요하지 않을수도 있습니다
765+
766+
[이 트윗](https://twitter.com/dan_abramov/status/1133878326358171650)에 따르면, defaultProps는 deprecate 될 것입니다.. 다음의 토론을 확인해 보세요.:
767+
768+
- [Original tweet](https://twitter.com/hswolff/status/1133759319571345408)
769+
- [이 article](https://medium.com/@matanbobi/react-defaultprops-is-dying-whos-the-contender-443c19d9e7f1)에서 더 많은 정보를 얻을 수 있습니다.
770+
771+
object default value를 사용하는 것이 통상적으로 합의된 내용입니다.
772+
773+
Function Components:
774+
775+
```tsx
776+
type GreetProps = { age?: number };
777+
778+
const Greet = ({ age = 21 }: GreetProps) => // etc
779+
```
780+
781+
Class Components:
782+
783+
```tsx
784+
type GreetProps = {
785+
age?: number;
786+
};
787+
788+
class Greet extends React.Component<GreetProps> {
789+
render() {
790+
const { age = 21 } = this.props;
791+
/*...*/
792+
}
793+
}
794+
795+
let el = <Greet age={3} />;
796+
```
797+
798+
#### `defaultProps` 타이핑 하기
799+
800+
[TypeScript 3.0+](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-0.html)에서 타입 추론의 성능이 매우 많이 발전되었습니다. 하지만 여전히 [몇몇의 edge case 들이 문제가 되기는 합니다.](https://github.com/typescript-cheatsheets/react/issues/61).
801+
802+
**Function Components**
803+
804+
```tsx
805+
// 쉬운 방법으로 typeof를 사용할 수 있습니다.; hoist되는 것에 주의하세요!
806+
// DefaultProps을 선언할 수도 있습니다.
807+
// e.g. https://github.com/typescript-cheatsheets/react/issues/415#issuecomment-841223219
808+
type GreetProps = { age: number } & typeof defaultProps;
809+
810+
const defaultProps = {
811+
age: 21,
812+
};
813+
814+
const Greet = (props: GreetProps) => {
815+
// etc
816+
};
817+
Greet.defaultProps = defaultProps;
818+
```
819+
820+
_[TS Playground에서 확인해보기](https://www.typescriptlang.org/play?#code/JYWwDg9gTgLgBAKjgQwM5wEoFNkGN4BmUEIcARFDvmQNwBQdMAnmFnAOKVYwAKxY6ALxwA3igDmWAFxwAdgFcQAIyxQ4AXzgAyOM1YQCcACZYCyeQBte-VPVwRZqeCbOXrEAXGEi6cCdLgAJgBGABo6dXo6e0d4TixuLzgACjAbGXjuPg9UAEovAD5RXzhKGHkoWTgAHiNgADcCkTScgDpkSTgAeiQFZVVELvVqrrrGiPpMmFaXcytsz2FZtwXbOiA)_
821+
822+
**Class components**의 경우, 타이핑을 위한 [두 가지 방법](https://github.com/typescript-cheatsheets/react/pull/103#issuecomment-481061483) (including using the `Pick` utility type)이 있지만, props definition을 거꾸로 수행("reverse") 하는 것을 추천합니다.
823+
824+
```tsx
825+
type GreetProps = typeof Greet.defaultProps & {
826+
age: number;
827+
};
828+
829+
class Greet extends React.Component<GreetProps> {
830+
static defaultProps = {
831+
age: 21,
832+
};
833+
/*...*/
834+
}
835+
836+
// Type-checks! type assertion이 필요 없음!
837+
let el = <Greet age={3} />;
838+
```
839+
840+
<details>
841+
<summary>라이브러리 작성자를 위한<b><code>JSX.LibraryManagedAttributes</code> 뉘앙스</b></summary>
842+
843+
위에서 소개된 구현은 앱 개발자들이 사용하는데 아무런 문제가 없습니다. 하지만 다른 사람들이 사용(consume)할 수 있도록 `GreetProps`를 export 하고은 경우도 있습니다. 여기서 `GreetProps`가 정의되는 방법이 문제가 됩니다. `age`는 꼭 필요하지 않을 때에도 `defaultProps`때문에 필수적인 props가 됩니다.
844+
845+
[`GreetProps`는 당신의 컴포넌트를 위한 _내부적인_ 규칙(컴포넌트가 구현하는 것)이지, _외부적인_ 것이 아닙니다](https://github.com/typescript-cheatsheets/react/issues/66#issuecomment-453878710). 따라서 export를 위한 type을 따로 만들 거나, `JSX.LibraryManagedAttributes` utility를 사용할 수도 있습니다.
846+
847+
```tsx
848+
// internal contract(내부적인 규칙), export 되어서는 안된다
849+
type GreetProps = {
850+
age: number;
851+
};
852+
853+
class Greet extends Component<GreetProps> {
854+
static defaultProps = { age: 21 };
855+
}
856+
857+
// external contract(외부적인 규칙)
858+
export type ApparentGreetProps = JSX.LibraryManagedAttributes<typeof Greet, GreetProps>;
859+
```
860+
861+
이렇게 하면 코드가 잘 실행되지만, `ApparentGreetProps`를 사용하는게 다소 번거로울 수 있습니다. 아래에서 설명하는 `ComponentProps` utility로 boilerplate를 간단하게 만들 수 있습니다.
862+
863+
</details>
864+
865+
#### defaultProps가 있는 Component의 props를 사용(consume)하기
866+
867+
`defaultProps`가 있는 컴포넌트는 실제로는 그렇지 않지만 필수적인 props를 가지는 것처럼 보일 수 있습니다.
868+
869+
##### Problem Statement
870+
871+
다음과 같은 작업을 하고싶다면,
872+
873+
```tsx
874+
interface IProps {
875+
name: string;
876+
}
877+
const defaultProps = {
878+
age: 25,
879+
};
880+
const GreetComponent = ({ name, age }: IProps & typeof defaultProps) => (
881+
<div>{`Hello, my name is ${name}, ${age}`}</div>
882+
);
883+
GreetComponent.defaultProps = defaultProps;
884+
885+
const TestComponent = (props: React.ComponentProps<typeof GreetComponent>) => {
886+
return <h1 />;
887+
};
888+
889+
// 'age' property는 '{ name: string; }'에 없지만, '{ age: number; } type에서는 필수적인 property 입니다.
890+
const el = <TestComponent name="foo" />;
891+
```
892+
893+
##### Solution
894+
895+
`JSX.LibraryManagedAttributes`를 적용하는 유틸리티를 정의합니다.
896+
897+
```tsx
898+
type ComponentProps<T> = T extends React.ComponentType<infer P> | React.Component<infer P>
899+
? JSX.LibraryManagedAttributes<T, P>
900+
: never;
901+
902+
const TestComponent = (props: ComponentProps<typeof GreetComponent>) => {
903+
return <h1 />;
904+
};
905+
906+
// No error
907+
const el = <TestComponent name="foo" />;
908+
```
909+
910+
[_TS Playground에서 확인해 보기_](https://www.typescriptlang.org/play?#code/JYWwDg9gTgLgBAKjgQwM5wEoFNkGN4BmUEIcARFDvmQNwBQdMAnmFnAMImQB2W3MABWJhUAHgAqAPjgBeOOLhYAHjD4ATdNjwwAdJ3ARe-cSyyjg3AlihwB0gD6Yqu-Tz4xzl67cl04cAH44ACkAZQANHQAZYAAjKGQoJgBZZG5kAHMsNQBBGBgoOIBXVTFxABofPzgALjheADdrejoLVSgCPDYASSEIETgAb2r0kCw61AKLDPoAXzpcQ0m4NSxOooAbQWF0OWH-TPG4ACYAVnK6WfpF7mWAcUosGFdDd1k4AApB+uQxysO4LM6r0dnAAGRwZisCAEFZrZCbbb9VAASlk0g+1VEamADUkgwABgAJLAbDYQSogJg-MZwYDoAAkg1GWFmlSZh1mBNmogA9Di8XQUfQHlgni8jLpVustn0BnJpQjZTsWrzeXANsh2gwbstxFhJhK3nIPmAdnUjfw5WIoVgYXBReKuK9+JI0TJpPs4JQYEUoNw4KIABYARjgvN8VwYargADkIIooMQoAslvBSe8JAbns7JTSsDIyAQIBAyOHJDQgA)
911+
912+
#### 여러가지 토론과 지식
913+
914+
<details>
915+
<summary><b><code>React.FC</code>는 왜 <code>defaultProps</code>이 동작하지 못하게 만들까요?</b></summary>
916+
917+
다음의 토론을 확인해 보세요.:
918+
919+
- https://medium.com/@martin_hotell/10-typescript-pro-tips-patterns-with-or-without-react-5799488d6680
920+
- https://github.com/DefinitelyTyped/DefinitelyTyped/issues/30695
921+
- https://github.com/typescript-cheatsheets/react/issues/87
922+
923+
이건 현재 상태일 뿐이고, 추후에는 올바르게 수정될 것입니다.
924+
925+
</details>
926+
927+
<details>
928+
<summary><b>TypeScript 2.9 and earlier</b></summary>
929+
930+
TypeScript 2.9와 그 이존 버전에서는 이문제를 해결하는 방법이 다양합니다. 하지만 다음 방법이 여태까지 확인한 방법 중 가장 좋은 방법입니다.
931+
932+
```ts
933+
type Props = Required<typeof MyComponent.defaultProps> & {
934+
/* 추가적인 props */
935+
};
936+
937+
export class MyComponent extends React.Component<Props> {
938+
static defaultProps = {
939+
foo: "foo",
940+
};
941+
}
942+
```
943+
944+
이전에는 TypeScript의 `Partial type` 기능을 사용하는 것이 권장 사항이었는데, 이는 현재 인터페이스가 래핑된 인터페이스에에서 부분적인 버전을 충족한다는 것을 의미합니다. 이런 방버으로 type을 변경하지 않고 defaultProps를 확장할 수 있습니다.
945+
946+
```ts
947+
interface IMyComponentProps {
948+
firstProp?: string;
949+
secondProp: IPerson[];
950+
}
951+
952+
export class MyComponent extends React.Component<IMyComponentProps> {
953+
public static defaultProps: Partial<IMyComponentProps> = {
954+
firstProp: "default",
955+
};
956+
}
957+
```
958+
959+
이 접근 방법의 문제점은 `JSX.LibraryManagedAttributes`로 작동하는 타입 추론에 복잡한 이슈를 발생시킨다는 것입니다. 기본적으로 컴파일러는 해당 컴포넌트로 JSX expression을 생성할 때 모든 props가 선택사항(optional)이라고 생각합니다.
960+
961+
[@ferdaber의 의견을 확인해 보세요.](https://github.com/typescript-cheatsheets/react/issues/57) and [here](https://github.com/typescript-cheatsheets/react/issues/61).
962+
963+
</details>
964+
965+
[추가할 내용이 있나요? 이슈를 생성하세요!](https://github.com/typescript-cheatsheets/react/issues/new).
966+
967+
<!--END-SECTION:default-props-->

0 commit comments

Comments
 (0)