🦧
ChatGPT先生にNext.jsでTODOアプリの作り方を教わる
プロンプトにて
todo application in nextjs
すべきことを教えてくれた
いつものように「Sure!, Here's an example of ...」とコードを吐き出してくれる。
まずは以下のコマンドを叩いてね。
npx create-next-app my-todo-app
cd my-todo-app
npm run dev
そして [pages/index.tsx」を以下にまるっと書き換えます。
index.tsx
import { useState } from 'react'
export default function Home() {
const [todos, setTodos] = useState([])
const [inputValue, setInputValue] = useState('')
const handleAddTodo = () => {
if (!inputValue) return
setTodos([...todos, inputValue])
setInputValue('')
}
const handleDeleteTodo = (index) => {
setTodos(todos.filter((_, i) => i !== index))
}
return (
<div>
<h1>Todo App</h1>
<input
type="text"
value={inputValue}
onChange={(e) => setInputValue(e.target.value)}
/>
<button onClick={handleAddTodo}>Add Todo</button>
<ul>
{todos.map((todo, index) => (
<li key={index}>
{todo}
<button onClick={() => handleDeleteTodo(index)}>Delete</button>
</li>
))}
</ul>
</div>
)
}
手直し
そのままだとTSによるエラーが残る
- useStateの型推論によるエラー
const todos: never[]
Type 'string' is not assignable to type 'never'.ts(2322)
- 型の不明記
(parameter) index: any
Parameter 'index' implicitly has an 'any' type.
TS対応版を知りたい
ということでもう一度ChatGPTに聞いてみましょう。
what about along with typescript?
そしたら以下のコードを教え得てくれます
型明記アリのTSXコード
import { useState } from 'react'
type Todo = {
id: number
text: string
}
export default function Home() {
const [todos, setTodos] = useState<Todo[]>([])
const [inputValue, setInputValue] = useState('')
const handleAddTodo = () => {
if (!inputValue) return
const newTodo: Todo = {
id: new Date().getTime(),
text: inputValue,
}
setTodos([...todos, newTodo])
setInputValue('')
}
const handleDeleteTodo = (id: number) => {
setTodos(todos.filter((todo) => todo.id !== id))
}
return (
<div>
<h1>Todo App</h1>
<input
type="text"
value={inputValue}
onChange={(e) => setInputValue(e.target.value)}
/>
<button onClick={handleAddTodo}>Add Todo</button>
<ul>
{todos.map((todo) => (
<li key={todo.id}>
{todo.text}
<button onClick={() => handleDeleteTodo(todo.id)}>Delete</button>
</li>
))}
</ul>
</div>
)
}
デザイン追加
このままだと味気ないので「Meterial UI」を使ったらどうなるでしょうか。
npm install @mui/material @mui/icons-material @emotion/styled @emotion/react
ChatGPTには以下のように聞いてデザイン付きのコードを吐いてもらいます。
if with dependency
npm install @mui/icons-material @mui/material @emotion/styled @emotion/react
デザイン付きindex.tsx
import { useState } from 'react'
import { styled } from '@mui/material/styles'
import { Button, TextField, List, ListItem, ListItemText, ListItemSecondaryAction, IconButton } from '@mui/material'
import { Delete } from '@mui/icons-material'
type Todo = {
id: number
text: string
}
const Root = styled('div')({
margin: 16,
})
const Input = styled(TextField)({
marginRight: 16,
})
export default function Home() {
const [todos, setTodos] = useState<Todo[]>([])
const [inputValue, setInputValue] = useState('')
const handleAddTodo = () => {
if (!inputValue) return
const newTodo: Todo = {
id: new Date().getTime(),
text: inputValue,
}
setTodos([...todos, newTodo])
setInputValue('')
}
const handleDeleteTodo = (id: number) => {
setTodos(todos.filter((todo) => todo.id !== id))
}
return (
<Root>
<h1>Todo App</h1>
<Input
label="Add Todo"
variant="outlined"
size="small"
value={inputValue}
onChange={(e) => setInputValue(e.target.value)}
/>
<Button variant="contained" onClick={handleAddTodo}>
Add
</Button>
<List>
{todos.map((todo) => (
<ListItem key={todo.id}>
<ListItemText primary={todo.text} />
<ListItemSecondaryAction>
<IconButton edge="end" aria-label="delete" onClick={() => handleDeleteTodo(todo.id)}>
<Delete />
</IconButton>
</ListItemSecondaryAction>
</ListItem>
))}
</List>
</Root>
)
}
最終的な画面
デフォルトのNext.jsのデザインも残っておしゃれなTODOアプリができましたね。
最終的なコード
今後の展開
追加機能は以下を想定しています
-データ保存(クッキー ot ローカルストレージ)
-アカウント別リスト(ログイン)
Discussion