props의 interface의 중복을 최소한으로 줄이기 위한 방법
interface ListProps<T> {
items: T[]; // Array<T>
handleClick: () => void;
}
const List = <T extends {}>({ items, handleClick }: ListProps<T>) => {
return (
<ul>
{items.map((item, index) => (
<li key={index} onClick={handleClick}>
{item}
</li>
))}
</ul>
);
}
type XPosition = "left" | "center" | "right";
type YPosition = "top" | "center" | "bottom";
type TicTacToeClassName = `${XPosition}-${YPosition}`;
/* ===
type TicTacToeClassName =
"left-top"
| "center-top"
| "right=top"
| ...
*/
const CustomButton: React.FC<React.ComponentProps<typeof Button>> = (props) => {
return (
<button style={props.styles} onClick={props.handleClick}>
{props.children}
</button>
);
}
export const Button = (props: React.PropsWithChildren<ButtonProps>) => {
return <button {...props} >{props.children}</button>
}
export const Button: React.FC<ButtonProps> = (props) => {
return <button {...props} >{props.children}</button>
}
type FC<P = {}> = FunctionComponent<P>;
interface FunctionComponent<P = {}> {
(props: PropsWithChildren<P>, context?: any): ReactElement<any, any> | null;
}
interface ButtonProps {
styles?: React.CSSProperties;
handleClick: (e: React.MouseEvent<HTMLButtonElement, MouseEvent>) => void;
}
export const Button: React.FC<ButtonProps> = (props) => {
const buttonStyles = createButtonStyle(props.styles);
return (
<button style={buttonStyles} onClick={props.handleClick}>
{props.children}
</button>
);
};
onClick={e => console.log(e)}
를 해보면 된다. // 1
function useState<S>(initialState: S | (() => S)): [S, Dispatch<SetStateAction<S>>];
// 2
function useState<S = undefined>(): [S | undefined, Dispatch<SetStateAction<S | undefined>>];
useState<String | null>(null)
type ScoreState = {
score: number;
}
type CounterAction = {
type: "INCREMENT" | "DECREMENT";
score: number;
}
type ResetAction = {
type: "RESET";
}
type ScoreAction = CounterAction | ResetAction; // RESET action시 score를 받지 않는 경우를 감안해 Union으로 구성
const reducer = (state: ScoreState, action: ScoreAction): ScoreState => {
swtich (action.type) {
case "INCREMENT":
return { score: state.score + action.score };
case "DECREMENT":
const result = state.score - action.score;
return { score: result < 0 ? 0 : result };
case "RESET":
return { score: 0 };
default:
return state;
}
}
export const ScoreCounter = () => {
const [score, dispatch] = React.useReducer(reducer, { score: 0 });
return <div>{score}</div>
}
interface ScoreContextValue {
score: number;
dispatch: Dispatch<ScoreAction>;
}
export const ScoreContest = createContext<ScoreContextValue>({
score: 0;
dispatch: () => {};
});