cra 환경에서 코드를 작성하였습니다.
Github 링크
https://github.com/mokyoungg/react_ts_todolist/blob/master/README.md
React에서 TS 설치하기
출처 : https://create-react-app.dev/docs/adding-typescript/
Create React App과 함께 설치하기
npx create-react-app my-app --template typescript
기존의 CRA 환경에 TS 추가하기
npm install --save typescript @types/node @types/react @types/react-dom @types/jest
이후 모든 파일의 이름을 TypeScript 파일로 변경하고 개발 서버를 재시작.
(src/index.js => src/index.tsx)
React와 TypeScript로 todolist 만들기
프로젝트 초기 설정(App.tsx)
![](https://velog.velcdn.com/images%2Fmokyoungg%2Fpost%2Fe103bc7f-ccbe-48b3-8092-4669cbd90bab%2Fimage.png)
- 파일명은 tsx로 만든다.(App.tsx)
- 해당 함수가(const App = () => {}) react 컴포넌트라는 것을 타입스크립트로 설정한다.
- FC는, FunctionComponent.(함수형 컴포넌트)
![](https://velog.velcdn.com/images%2Fmokyoungg%2Fpost%2Fe18a1a66-286e-4b7d-a866-d489cc0ac84b%2Fimage.png)
- App 함수의 타입을 컴포넌트로 정의한 이후 해당 함수가 일반 함수라면 오류가 발생한다.
타입스크립트에서 props 사용
App.tsx
![](https://velog.velcdn.com/images%2Fmokyoungg%2Fpost%2F646abdab-2205-4f2c-ad56-dafd390d3ebb%2Fimage.png)
TodoList.tsx
![](https://velog.velcdn.com/images%2Fmokyoungg%2Fpost%2F1d7bf858-b9de-4951-a5b7-8a18da802357%2Fimage.png)
- App 컴포넌트에서 정의한 todos 라는 배열을 TodoList 컴포넌트에 props로 전달한다.
- TodoList 컴포넌트에선 전달받은 props를 활용하여 페이지를 보여준다.
React에서 사용하는 가장 기본적인 사항이 타입스크립트에서 사용하면 에러가 발생한다.
![](https://velog.velcdn.com/images%2Fmokyoungg%2Fpost%2Fb9064e9e-3b31-452e-a636-8965fbe59519%2Fimage.png)
이는 property 가 존재하기 않기 때문에 컴파일 오류가 발생한것이다.
타입스크립트가 props를 얻고 이를 활용하는 것을 이해하지 못했기 때문이다.
App.tsx에서 TodoList로 props 전달
![](https://velog.velcdn.com/images%2Fmokyoungg%2Fpost%2F96aac499-180d-4f52-a4d9-b44c09d48cdc%2Fimage.png)
- App에서 전달되는 props를 타입스크립트로 설정한다.(interface TodoListProps)
- 컴포넌트에 <>를 사용하여 설정한 props를 추가한다.(타입스크립트 제네릭)
- 이를 통해 타입스크립트에선 props를 이해하고 오류를 발생시키지 않는다.
useRef와 타입스크립트(NewTodo 컴포넌트 제작)
![](https://velog.velcdn.com/images%2Fmokyoungg%2Fpost%2Fe1c19cec-0531-461d-a12d-451a67e7a0c2%2Fimage.png)
![](https://velog.velcdn.com/images%2Fmokyoungg%2Fpost%2F086efcde-382f-420e-8f06-ce1bdc8981f8%2Fimage.png)
- todolist에 해야할 일을 추가하기 위해 NewTodo 컴포넌트를 만들었다.
- 해당 컴포넌트에서 input 태그에 접근하기 위해 useRef를 사용했지만 타입스크립트에서 오류가 발생한다.
![](https://velog.velcdn.com/images%2Fmokyoungg%2Fpost%2Fc1eddbcd-dd14-4625-84a3-238c32ef7ce2%2Fimage.png)
- textInputRef가 참조하는 대상이 HTML의 Input 요소라는 것을 알려준다.
- 해당 코드가 실행될 때(처음 컴포넌트가 렌더링될때) null 값을 가지게 된다.
- 렌더링이 되고 나면 연결이 설정되고 해당 참조가 작동하게 된다.(null에서 input 태그로)
컴포넌트간의 커뮤니케이션(state 조작)
NewTodo 컴포넌트에서 작성한 text를 App 컴포넌트의 todos 에 추가한다.
useState 사용하기
![](https://velog.velcdn.com/images%2Fmokyoungg%2Fpost%2Fb92e0291-de42-43f4-a2d1-1e859b03d63f%2Fimage.png)
- React Hooks의 useState를 사용하려면 해당 state의 타입을 설정해줘야한다.
- todos(state)의 형태는 배열이고, 해당 배열의 요소는 객체이며 객체의 키에 해당하는 id와 text는 string 타입을 가지고 있다.
더 깔끔하게 사용하기(todo.model.ts 의 사용)
![](https://velog.velcdn.com/images%2Fmokyoungg%2Fpost%2F347a469f-1cc6-4be0-9a07-1808f45bdb2e%2Fimage.png)
![](https://velog.velcdn.com/images%2Fmokyoungg%2Fpost%2Ff2102e5f-ff85-4810-bb16-308e292d9295%2Fimage.png)
- 코드를 깔끔하게 쓰기 위해 Todo라는 interface 를 todo.model.ts라는 파일에서 작성.
- 이후 작성한 인터페이스를 import 하여 사용한다.
함수 전달하기
![](https://velog.velcdn.com/images%2Fmokyoungg%2Fpost%2Fe3da11dd-8b55-47eb-ba18-dd9330370964%2Fimage.png)
- todos(state)를 조작하는 todoAddHandler 라는 함수를 자식 컴포넌트인 NewTodo 컴포넌트에 전달한다.
- 처음 props를 전달했을때와 같은 이유로 오류가 발생한다.
![](https://velog.velcdn.com/images%2Fmokyoungg%2Fpost%2F82009e54-20cd-4b91-8b50-d0546b575826%2Fimage.png)
- 자식컴포넌트인 NewTodo 컴포넌트에서 props를 정의한다.
- props로 받는 onAddTodo는 함수형 타입이며 인자로 string 타입을 받는다.
- 이제 해당 함수를 props.함수이름 으로 사용할 수 있다.
기능 추가하기(todlist 지우기)
![](https://velog.velcdn.com/images%2Fmokyoungg%2Fpost%2F65caef32-d314-414c-8768-0433721ebcf9%2Fimage.png)
- App 컴포넌트에서 todos(state)이 요소를 지우는 함수인 todoDeleteHandler 라는 함수를 작성함.(filter를 통해 id의 값을 비교하여 같은 id는 지움)
- 해당 함수를 TodoList 컴포넌트에 전달
![](https://velog.velcdn.com/images%2Fmokyoungg%2Fpost%2Fbd288a3f-342a-4d81-a6c8-f278ce488bac%2Fimage.png)
- 자식 컴포넌트인 TodoList 컴포넌트에서 props로 받아오는 함수의 타입을 정의한다.
- 기존에 작성했던 TodoListProps에서 onDeleteTodo 를 string을 인자로 받는 함수 타입으로 설정
- 해당 함수를 button 태그의 onClick 이벤트로 설정한다.
참조