[TypeScript] React 에서 활용

JoGabi·2022년 3월 11일
2

TypeScript

목록 보기
6/8
post-thumbnail

리엑트에서 타입스크립트 사용할때 어떤식으로 사용을 해야하는지 알아보려고 한다.

파일형식

타입스크립트가 세팅되어있는 리엑트 프로젝트 세팅 할때 기본 파일형식은 .tsx 로 되어있다.

JSX 문법을 쓰는 파일은 .tsx
일반 파일은 .ts

JSX 타입

리엑트에서 JSX 를 변수에담아 표현하는 타입이 있다.

let box: JSX.Element = <div>헬로우</div>;

function App() {
  return (
    <div>
      {box}
      <h4>안녕</h4>
    </div>
  );
}

조금더 정확히 지정하고 싶을떄
html 기본태그들을 미리 정의해놓은 타입

let box: JSX.IntrinsicElements["div"] = <div>헬로우</div>;

component 타입

파라미터 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>;
}

props 타입

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>
  );
}

useState 타입

사실 자동으로 지정해줘서 신경 쓰지 않아도 된다

하지만 string|number 타입 넣고싶다면 ? (거의안써..)

generic type 이용 해서 타입지정해줌

function App() {
  const [state, setState] = useState<string | number>("jogabi"); //generic type
  return (
    <div>
      <h4>안녕</h4>
    </div>
  );
}

Redux 타입

두둥 Redux 타입을 지정 해보자

리덕스 사용하는 이유 ?

간단요약 : 모든 컴포넌트들이 props없이~ state 공유가 가능!

타입지정 방법

예시 버튼을 눌렀을때 1씩 더해주는 기능 만들기

  • useSelector 컴포넌트에 redux에서 만든 state 쓸때
    꺼내온것 (콜백함수 들어감)
  • 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")
);
  • state 초기값 타입 지정
    state 수정 방법을 한 파일에 정의해두고 불러올 수 있음 (버그추적 쉬움)
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;
  }
}
  • functionn props 타입 지정
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")
);
  

리덕스를 도와주는 라이브러리

reduxjs/toolkit

장점

  1. 함수형식으로 코드가 깔끔해짐
  2. 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개의 속성이 들어가야함

  • name
  • initialState
  • reducers(데이터수정법)

(state + reducer 합친걸 slice 라고함)

free(state, action) action 에서 타입 지정할때

import {  PayloadAction } from @reduxjs/toolkit"; 

import 해주고
dispatch() 할때 숫자 추가하기위해 제네릭 써줌

free(state, action: PayloadAction<number>) 

스테이트 꺼낼때

useSelector 똑같이 함
꺼낼때 store에 등록할떄 counter로 등록했기 때문에
{setUser.counter.count 로 지정해서 꺼내야함

dispatch 할때

용법이 조금다르다.

  onClick={() => {
	  dispatch(dispatch(plus()));
  }}

여기서 plus는 index.tsx 에서 export한 함수이다.

profile
서울에서 프론트엔드 개발자로 일하고 있는 Gabi 입니다. 프론트엔드: Javascript, React, TypeScript 에 관심이 있습니다.

0개의 댓글

관련 채용 정보