/React-toDo

This is a to-do app following the tutorial found at https://towardsdatascience.com/build-a-simple-todo-app-using-react-a492adc9c8a4

Primary LanguageJavaScript

Simple React Todo App with Storybook

Contents
About Links
Steps

About

This Todo App is built following the "Build a Simple Todo App using React" by Kumar Shubham, and the Storybook.js tutorial.

This App follows and is adapted from the tutorials "Build a Simple Todo App using React" and the basic storybook.js tutorial. The main ambition of this repo/app is to outline a todo template for myself while familiarizing myself with storybook.js for future projects.

Steps

1. Create the app
1.1- Create React App

npx create-react-app todo

1.2- Switch into the todo directory

cd todo

2. Setup storybook.js
2.1- Install storybook.js

npx sb init

2.2- Run storybook.js

yarn storybook
-or if you prefer npm-
npm run storybook

Troubleshooting
babel-loader error

In todo/package.json, add

"resolutions": {
  "babel-loader": "8.1.0"
 }

to the bottom

3. Make it do something
3.1- Imports

Add to the top:

 import { Button, Card, Form } from 'react-bootstrap'
 import 'bootstrap/dist/css/bootstrap.min.css'
3.2- Functions
3.2.1- Todo()
function Todo({ todo, index, markTodo, removeTodo }) {
  return (
    <div className="todo">
      <span style={{ textDecoration: todo.isDone ? "line-through" : "" }}>
        {todo.text}
      </span>
      <div>
        <Button variant="outline-success" onClick={() => markTodo(index)}>
          ✓
        </Button>
        {' '}
        <Button variant="outline-danger" onClick={() => removeTodo(index)}>
          ✕
        </Button>
      </div>
    </div>
  )
}
3.2.2- FormTodo()
3.2.2.1- useState()

const [value, setValue] = React.useState("")

3.2.2.2- handleSubmit()
const handleSubmit = e => {
  e.preventDefault()
  if (!value) return
  addTodo(value)
  setValue("")
}
3.2.2.3- return()
return (
  <Form onSubmit={handleSubmit}>
    <Form.Group>
      <Form.Label>
        <b>Add Todo</b>
      </Form.Label>
      <Form.Control
        type="text"
        className="input"
        value={value}
        onChange={e => setValue(e.target.value)}
        placeholder="Add new todo"
      />
      <Button variant="primary mb-3" type="submit">
        Submit
      </Button>
    </Form.Group>
  </Form>
)
3.2.3- App()
3.2.3.1- useState()
const [todos, setTodos] = React.useState([
  {
    text: "This is a sample todo",
    isDone: false
  }
])
3.2.3.2- addTodo()
const addTodo = text => {
  const newTodos = [...todos, { text }]
  setTodos(newTodos)
}
3.2.3.3- markTodo()
const markTodo = index => {
  const newTodos = [...todos]
  newTodos[index].isDone = true
  setTodos(newTodos)
}
3.2.3.4- removeTodo()
const removeTodo = index => {
  const newTodos = [...todos]
  newTodos.splice(index, 1)
  setTodos(newTodos)
}
3.2.3.5- return()
return (
  <div className="app">
    <div className="container">
      <h1 className="text-center mb-4">
        Todo List
      </h1>
      <FormTodo addTodo={addTodo} />
      <div>
        {todos.map((todo, index) => (
          <Card>
            <Card.Body>
              <Todo
                key={index}
                index={index}
                todo={todo}
                markTodo={markTodo}
                removeTodo={removeTodo}
              />
            </Card.Body>
          </Card>
        ))}
      </div>
    </div>
  </div>
)
3.3- Complete App.js
 import React from "react"
 import './App.css';
 import { Button, Card, Form } from 'react-bootstrap'
 import 'bootstrap/dist/css/bootstrap.min.css'
 
 function Todo({ todo, index, markTodo, removeTodo }) {
   return (
     <div className="todo">
       <span style={{ textDecoration: todo.isDone ? "line-through" : "" }}>
         {todo.text}
       </span>
       <div>
         <Button variant="outline-success" onClick={() => markTodo(index)}>
           ✓
         </Button>
         {' '}
         <Button variant="outline-danger" onClick={() => removeTodo(index)}>
           ✕
         </Button>
       </div>
     </div>
   )
 }
 
 function FormTodo({ addTodo }) {
   const [value, setValue] = React.useState("")
   
   const handleSubmit = e => {
     e.preventDefault()
     if (!value) return
     addTodo(value)
     setValue("")
   }
   
   return (
     <Form onSubmit={handleSubmit}>
       <Form.Group>
         <Form.Label>
           <b>Add Todo</b>
         </Form.Label>
         <Form.Control
           type="text"
           className="input"
           value={value}
           onChange={e => setValue(e.target.value)}
           placeholder="Add new todo"
         />
         <Button variant="primary mb-3" type="submit">
           Submit
         </Button>
       </Form.Group>
     </Form>
   )
 }
 
 function App() {
   const [todos, setTodos] = React.useState([
     {
       text: "This is a sample todo",
       isDone: false
     }
   ])
   
   const addTodo = text => {
     const newTodos = [...todos, { text }]
     setTodos(newTodos)
   }
   
   const markTodo = index => {
     const newTodos = [...todos]
     newTodos[index].isDone = true
     setTodos(newTodos)
   }
   
   const removeTodo = index => {
     const newTodos = [...todos]
     newTodos.splice(index, 1)
     setTodos(newTodos)
   }
   
   return (
     <div className="app">
       <div className="container">
         <h1 className="text-center mb-4">
           Todo List
         </h1>
         <FormTodo addTodo={addTodo} />
         <div>
           {todos.map((todo, index) => (
             <Card>
               <Card.Body>
                 <Todo
                   key={index}
                   index={index}
                   todo={todo}
                   markTodo={markTodo}
                   removeTodo={removeTodo}
                 />
               </Card.Body>
             </Card>
           ))}
         </div>
       </div>
     </div>
   )
 }
 
 export default App;

Links

Relevant Links