This is a solution of Todo app challenge from Dev Challenges.
Users should be able to:
- Add a new task.
- Complete a task.
- Toggle between All, Active and Completed.
- Remove one or all tasks under the Completed tab.
- Store the data in local storage that when I refresh the page I can still see my progress.
- Live Demo: Demo
- Semantic HTML5 markup
- Flexbox
- CSS Grid
- JavaScript ES6+
- React - JS library
- Styled Components - For styles
- Vite - Bundle tool
- Standard - Linter
This was an interesting challenge to practice with React.
Created customs hooks
to improve readability of components and simplify the use of logic in components.
//This hook is helpful to handle the localStorage data saving.
export const useLocalStorage = (keyName, initialValue) => {
const [storeItem, setStoreItem] = useState(initialValue)
//Here you can save a new value for the giving key, thanks to this function you don't have to worry about the parsing.
const setNewValue = (value) => {
const stringData = JSON.stringify(value)
localStorage.setItem(keyName, stringData)
setStoreItem(value)
}
// Similar to setNewValue, this function helps you to get the data from the given key in localStorage without worrying about parsing.
const getStoreItem = (key) => {
return JSON.parse(localStorage.getItem(key))
}
// Here is set the first value of the given key, if there is no values is set to the initialValue parameter.
useEffect(() => {
const storeStarter = getStoreItem(keyName) ?? initialValue
setStoreItem(storeStarter)
}, [])
return [
storeItem,
setNewValue
]
}
// Usage
//Note: this is very similar to react's useState hook, the only difference is that you have to set a keyname as first the argument.
const [storageValue, setStorageValue] = useLocalStorage('key_name',initialValue)
Created activeState
css helper function to add the blue border on tabs when they are active. This is trigger with the components props.
const activeState = css`
border-bottom: 2px solid ${color.main};
&::after {
content: '';
position: absolute;
bottom: 0;
right: 0;
width: 100%;
height: 3px;
background-color: ${color.main};
border-radius: 4px 4px 0px 0px;
}
`
// When the component is active the `activeState` css is added.
export const TaskTab = styled.div`
position: relative;
min-width: 90px;
padding-block: 1em;
font-weight: ${weight.semiBold};
cursor: pointer;
${props => props.active === true ? activeState : ''};
`
Made the code less compact but more verbose
//hooks/useTasks.js
//I prefer to create a constant to hold the array updating and then set that variable in the `setTasks()` function.
//In this way the code set function looks cleaner and is more understandable what is changing and how.
const createTask = (newTask) => {
if (newTask.trim()) {
const updatedTasks = [
...tasks,
{ text: newTask, completed: false }
]
setTasks(updatedTasks)
}
}
const completeTask = ({ target }) => {
const currentId = target.parentElement.id
const updatedTasks = tasks.map(task => {
if (task.text === currentId) return { ...task, completed: !task.completed }
return task
})
setTasks(updatedTasks)
}
const deleteTask = ({ target }) => {
const currentId = target.id
const updatedTasks = tasks.filter(task => task.text !== currentId)
setTasks(updatedTasks)
}
const deleteAllTasks = () => {
const updatedTasks = tasks.filter(task => !task.completed)
setTasks(updatedTasks)
}
Last but not least, this is the cool tip that I get from the bobby's article.
//There are different ways to do this but I think this approach looks cleaner and understandable
const newArray = array.map(item => {
if (item.id === expectedId) return { ...item, completed: !item.completed }
return item
})
-
Styled Components docs - The official documentation of styled components, this resource was very useful to understand this package.
-
LocalStorage Web API - This is a great article to understand the basis of
LocalStorage
. With this I could implement thepersistent data
feature. -
Curso Introducción a React - This is a great course to learn the basis of
react
. This was really helpful in thelocalStorage
section to create and use acustom hook
. -
Trash icon by mithun - This icon is free to use and very helpful for the
delete
functionality. -
Update Object's properties in Array - This was an excellent article to get a new idea of how to update object's properties inside an Array of objects.
-
Refactor React Components - This is a great video from
@midudev
to understand the why and how to use thecustom hooks
in order to make the code cleaner.
To test this project by yourself first clone the repository, then you can use this commands:
Install project
npm install
Run local server
npm run dev
Build project
npm run build
Preview Build
npm run preview