리엑트에서 타입스크립트 사용할때 어떤식으로 사용을 해야하는지 알아보려고 한다.
타입스크립트가 세팅되어있는 리엑트 프로젝트 세팅 할때 기본 파일형식은 .tsx
로 되어있다.
JSX 문법을 쓰는 파일은 .tsx
일반 파일은 .ts
리엑트에서 JSX 를 변수
에담아 표현하는 타입이 있다.
let box: JSX.Element = <div>헬로우</div>;
function App() {
return (
<div>
{box}
<h4>안녕</h4>
</div>
);
}
조금더 정확히
지정하고 싶을떄
html 기본태그들을 미리 정의해놓은 타입
let box: JSX.IntrinsicElements["div"] = <div>헬로우</div>;
파라미터
return 값
에 대한 함수의 타입지정이 가능하다.
let box: JSX.IntrinsicElements["div"] = <div>헬로우</div>;
function App() {
return (
<div>
{box}
<h4>안녕</h4>
<People></People>
</div>
);
}
function People(): JSX.Element {
//return 123 // 에러
return <div>사람</div>;
}
function App() {
return (
<div>
<h4>안녕</h4>
<People id={123} name="gabi"></People>
</div>
);
}
function People(props: { name: string; id: number }): JSX.Element {
return (
<div>
{props.name} {props.id}
</div>
);
}
사실 자동으로 지정해줘서 신경 쓰지 않아도 된다
하지만 string|number
타입 넣고싶다면 ? (거의안써..)
generic type 이용 해서 타입지정해줌
function App() {
const [state, setState] = useState<string | number>("jogabi"); //generic type
return (
<div>
<h4>안녕</h4>
</div>
);
}
두둥 Redux 타입을 지정 해보자
간단요약 : 모든 컴포넌트들이 props없이~ state 공유
가 가능!
예시 버튼을 눌렀을때 1씩 더해주는 기능 만들기
useSelector
컴포넌트에 redux에서 만든 state 쓸때귀찮을때
store 타입 미리 export 함//App.tsx
import { RootState } from "./index";
const setUser = useSelector((state: RootState) => state);
const dispatch: Dispatch = useDispatch();
//index.tsx
const setUser = useSelector((state: RootState) => state);
const store = createStore(reducer);
export type RootState = ReturnType<typeof store.getState>;
ReactDOM.render(
<React.StrictMode>
<Provider store={store}>
<App />
</Provider>
</React.StrictMode>,
document.getElementById("root")
);
const setUser: { count: number } = { count: 0 };
function reducer(state = setUser, action: { type: string }) {
if (action.type === "plus") {
return { ...state, count: state.count + 1 };
} else if (action.type === "minus") {
return { ...state, count: state.count - 1 };
} else {
return setUser;
}
}
const store = createStore(reducer);
<Provider store={store}>
...
</Provider>
state를 담은 store 을 만든 다음 모든 컴포넌트 들이 이용할 수 있게 싸맸음
reducer() 의 state 파라미터는 자동타입 지정해주기 때문에 생략해도 됨
action
: 다른 파일의 컴포넌트안에서 dispatch() 할때 넣는 파라미터랑 같은것
dispatch 도 타입지정 가능
const dispatch: Dispatch = useDispatch();
완성
//App.tsx
import { RootState } from "./index";
import { Dispatch } from "redux";
function App() {
const setUser = useSelector((state: RootState) => state);
const dispatch: Dispatch = useDispatch();
return (
<div className="App">
{setUser.count}
<button
onClick={() => {
dispatch({ type: "plus" });
}}
>
버튼
</button>
</div>
);
}
//index.tsx
import { createStore } from "redux";
import { Provider } from "react-redux";
const setUser: { count: number } = { count: 0 };
function reducer(state = setUser, action: { type: string }) {
if (action.type === "plus") {
return { ...state, count: state.count + 1 };
} else if (action.type === "minus") {
return { ...state, count: state.count - 1 };
} else {
return setUser;
}
}
const store = createStore(reducer);
export type RootState = ReturnType<typeof store.getState>;
ReactDOM.render(
<React.StrictMode>
<Provider store={store}>
<App />
</Provider>
</React.StrictMode>,
document.getElementById("root")
);
장점
- 함수형식으로 코드가 깔끔해짐
- state 수정시 사본 안만들어도됨
// App.tsx
import reportWebVitals from "./reportWebVitals";
import { Provider } from "react-redux";
import { configureStore, createSlice, PayloadAction } from "@reduxjs/toolkit";
const setUser: { count: number } = { count: 0 };
const counterSlice = createSlice({
name: "counter",
initialState: setUser,
reducers: {
plus(state) {
state.count += 1;
},
minus(state) {
state.count -= 1;
},
free(state, action: PayloadAction<number>) {
state.count += action.payload;
},
},
});
let store = configureStore({
reducer: {
counter: counterSlice.reducer,
},
});
export type RootState = ReturnType<typeof store.getState>;
export let { plus, minus, free } = counterSlice.actions; //꺼내쓸때 함수지정
ReactDOM.render(
<React.StrictMode>
<Provider store={store}>
<App />
</Provider>
</React.StrictMode>,
document.getElementById("root")
);
reportWebVitals();
// index.tsx
function App() {
const setUser = useSelector((state: RootState) => state);
const dispatch: Dispatch = useDispatch();
return (
<div className="App">
{setUser.counter.count}
<button
onClick={() => {
dispatch(dispatch(plus()));
}}
>
버튼
</button>
</div>
);
}
createSlice
의 함수를 이용해서 state,reducers,name 작명을 하면 된다
createSlice 안에는 3개
의 속성이 들어가야함
(state + reducer 합친걸 slice 라고함)
import { PayloadAction } from @reduxjs/toolkit";
import 해주고
dispatch() 할때 숫자 추가하기위해 제네릭 써줌
free(state, action: PayloadAction<number>)
useSelector 똑같이 함
꺼낼때 store에 등록할떄 counter로 등록했기 때문에
{setUser.counter.count
로 지정해서 꺼내야함
용법이 조금다르다.
onClick={() => {
dispatch(dispatch(plus()));
}}
여기서 plus는 index.tsx 에서 export한 함수이다.