Last active
January 1, 2023 11:06
-
-
Save anhdiepmmk/bab883e2c598d62c75df0cf1ae68f7af to your computer and use it in GitHub Desktop.
reactjs typescript todo list
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// --------------------- 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