Skip to content

Instantly share code, notes, and snippets.

@anhdiepmmk
Last active January 1, 2023 11:06
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save anhdiepmmk/bab883e2c598d62c75df0cf1ae68f7af to your computer and use it in GitHub Desktop.
Save anhdiepmmk/bab883e2c598d62c75df0cf1ae68f7af to your computer and use it in GitHub Desktop.
reactjs typescript todo list
import { useState, useRef, KeyboardEvent, useEffect } from 'react'
const TODO_KEY = 'todos'
function App() {
const inputRef = useRef<HTMLInputElement>(null)
const [todos, setTodos] = useState<string[]>(() => {
const todoStr: string | null = localStorage.getItem(TODO_KEY)
if (todoStr) {
return JSON.parse(todoStr)
}
return []
})
useEffect(() => {
localStorage.setItem(TODO_KEY, JSON.stringify(todos))
}, [todos])
const handleAdd = () => {
const value: string | undefined = inputRef.current?.value
if (value) {
const newTodos = [...todos, value]
setTodos(newTodos)
inputRef.current!.value = ''
inputRef.current?.focus()
}
}
const handleRemove = (index: number) => {
const newTodos = [...todos]
newTodos.splice(index, 1)
setTodos(newTodos)
}
const handleKeyDown = (e: KeyboardEvent<HTMLInputElement>) => {
if (e.key === 'Enter') {
handleAdd()
}
}
return (
<div>
<div>
<input ref={inputRef} onKeyDown={handleKeyDown} />
<button onClick={handleAdd}>Add</button>
</div>
<ul>
{todos.map((todo, index) => {
return <li key={index}>{todo}<button onClick={() => handleRemove(index)}>clear</button></li>
})}
</ul>
</div>
)
}
export default App
import { useState, useRef, KeyboardEvent, useEffect, useReducer } from 'react'
const TODO_KEY = 'todos'
const initState = (() => {
const todoStr: string | null = localStorage.getItem(TODO_KEY)
if (todoStr) {
return JSON.parse(todoStr)
}
return []
})()
function reducer(todos: string[], action: { type: string, payload: any }) {
switch (action.type) {
case 'add':
const newTodo: string = action.payload as string
return [...todos, action.payload]
case 'remove':
const index: number = action.payload as number
todos.splice(index, 1)
return todos
default:
return todos
}
}
function App() {
const [todos, dispatch] = useReducer(reducer, initState)
const inputRef = useRef<HTMLInputElement>(null)
useEffect(() => {
localStorage.setItem(TODO_KEY, JSON.stringify(todos))
}, [todos])
const handleAdd = () => {
const value: string | undefined = inputRef.current?.value
if (value) {
dispatch({
type: 'add',
payload: value,
})
inputRef.current!.value = ''
inputRef.current?.focus()
}
}
const handleRemove = (index: number) => {
dispatch({
type: 'add',
payload: index,
})
}
const handleKeyDown = (e: KeyboardEvent<HTMLInputElement>) => {
if (e.key === 'Enter') {
handleAdd()
}
}
return (
<div>
<div>
<input ref={inputRef} onKeyDown={handleKeyDown} />
<button onClick={handleAdd}>Add</button>
</div>
<ul>
{todos.map((todo, index) => {
return <li key={index}>{todo}<button onClick={() => handleRemove(index)}>clear</button></li>
})}
</ul>
</div>
)
}
export default App
// --------------------- store.ts
import { configureStore } from "@reduxjs/toolkit";
import todoSlice from "./todo-slice";
export const store = configureStore({
reducer: {
todo: todoSlice.reducer,
}
})
// ---------------------- main.tsx
import React from 'react'
import ReactDOM from 'react-dom/client'
import App from './App'
import './index.css'
import { Provider } from 'react-redux'
import { store } from './store'
ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render(
<React.StrictMode>
<Provider store={store}>
<App />
</Provider>
</React.StrictMode>,
)
// ---------------------- todo-slice.ts
import { createSlice } from '@reduxjs/toolkit'
const todoSlice = createSlice({
initialState: [],
name: 'todo',
reducers: {
add(todos: string[], action : { payload : string }) {
todos.push(action.payload)
},
remove(todos: string[], action: { payload : number }) {
todos.splice(action.payload, 1)
}
}
})
export const todoActions = todoSlice.actions
export default todoSlice
// -------------------------- App.tsx
import { useRef, KeyboardEvent } from 'react'
import { useDispatch, useSelector } from 'react-redux'
import { todoActions } from './todo-slice'
function App() {
const todos: string[] = useSelector((state: any) => state.todo)
const dispatch = useDispatch()
const inputRef = useRef<HTMLInputElement>(null)
const handleAdd = () => {
const value: string | undefined = inputRef.current?.value
if (value) {
dispatch(todoActions.add(value))
inputRef.current!.value = ''
inputRef.current?.focus()
}
}
const handleRemove = (index: number) => {
dispatch(todoActions.remove(index))
}
const handleKeyDown = (e: KeyboardEvent<HTMLInputElement>) => {
if (e.key === 'Enter') {
handleAdd()
}
}
return (
<div>
<div>
<input ref={inputRef} onKeyDown={handleKeyDown} />
<button onClick={handleAdd}>Add</button>
</div>
<ul>
{todos.map((todo, index) => {
return <li key={index}>{todo}<button onClick={() => handleRemove(index)}>clear</button></li>
})}
</ul>
</div>
)
}
export default App
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment