PedroGeoGISdev wiki
  • Home
  • Linux OS
    • Linux: concepts
    • Linux: basic concepts
    • Linux: Bash
    • Linux: su and sudo
    • Linux: pipes
    • Linux: File System
    • Linux: Virtual Machines

    • Linux: distros
    • Linux Distros: Ubuntu
    • Linux Distros: Mint
    • Linux Distros: Debian
    • Linux Distros: openSuse
    • Linux Distros: Manjaro
    • Linux Distros: Red Hat Enterprise

    • Linux: laboratories
    • Linux Lab#LI01-1: Choose Linux
    • Linux Lab#LI01-2: Install at least three distributions
    • Linux Lab#LI01-3: Adjust user permissions
    • Linux Lab#LI02-1: Export env user with grep and pipe
    • Linux Lab#LI03-1: Manage users and groups
    • Linux Lab#LI03-2: Manage files
    • Linux Lab#LI03-3: Manage software
    • Linux Lab#LI03-4: Manage hardware
    • Linux Lab#LI04-1: Bash scripting, qtool
    • Linux Lab#LI04-2: Bash scripts as terminal tool
    • Linux Lab#LI04-3: Distribute the terminal app

    • Linux readings
    • Linux Resources
  • DevOps
    • What is DevOps
    • DevOps: Introduction
    • DevOps: Agile and Microservices
    • Infrastructure as code (IaC)
    • Immutable Infrastructure
    • Software Lifecycle

    • Documentation
    • How to document: Quarto and Obsidian

    • Network protocols
    • Network: Basics
    • Network: Client-server
    • Network Protocols
    • Network: DNS
    • Network: API Rest
    • Network: gRPC
    • Network: Websocket
    • Network: SMTP
    • Network: Ping
    • Network: UDP
    • Network: webhook
    • Network: SOAP
    • Network: graphQL

    • Version Control
    • Git
    • GitHub
    • Idea and GitHub 2023
    • Git and GitHub 2023 CLI

    • IDEs
    • IDE: Visual Code
    • IDE: IntellJIdea

    • DevOps tools
    • Amazon Web Services AWS
    • Docker
    • Jenkins pipelines
    • Kubernetes k8s
    • Digital Ocean
    • Nagios
    • Ansible

    • DevOps Laboratories
    • Lab 1: chat App
    • Lab 2: Spring Boot AWS AEB manually
    • Lab 3: Spring Boot and AWS S3 publisher
    • Lab 4: Spring Boot Docker/Jenkins
    • Lab 5: k8s on Digital Ocean
    • Lab 6: Spring Boot AWS codecommit

    • DevOps readings
    • DevOps Resources
  • MarkUp
    • MarkUp Languages
    • Introduction Markup
    • HTML Markup
    • Markdown Markup
    • Markdown and HTML working together, good idea?

    • Quarto Markdown
    • Quarto Markdown: basics
    • Quarto Markdown: creating
    • Quarto Markdown: publishing
    • Quarto Markdown: code & data
    • Quarto Markdown: api rest call
    • Quarto Markdown: OJS Cells
    • Quarto Markdown: cheat-sheet

    • Styling: CSS
    • Cascade Style Sheet
    • Cascade Style Sheet: Box Model and Containers
    • CSS: W3.css

    • MarkUp Languages Laboratories
    • Lab#MD01-1: Create and publish by Quarto

    • MarkUp Languages readings
    • MarkUp Languages Resources
  • Java SE
    • What is Java SE
    • Java Standard Edition: Basics
    • Java Standard Edition: Principles
    • Java MOOC Helsinki
    • Java MOOC Helsinki Syllabus

    • Java Create Project
    • Java SE: Maven
    • Java SE: Create Maven Project
    • Java SE: Project push GitHub
    • Java SE: JUnit and TDD

    • Java Concepts
    • Java SE: Class and Objects
    • Java SE: Scope
    • Java SE: static modifier
    • Java SE: Coupling and DDD
    • Java SE: Packages
    • Java SE: Abstract/Interface
    • Java SE: Java 8

    • Java Principles
    • Java SE: Encapsulation
    • Java SE: Abstraction
    • Java SE: Inherence
    • Java SE: Polymorphism

    • Java Design Patterns
    • Java Patterns: UML
    • Java Patterns: Types
    • Singleton
    • Factory
    • Abstract Factory
    • Builder
    • Facade
    • Bridge
    • Decorator
    • Composite
    • Observer
    • Strategy
    • State
    • Commander

    • Java SE Laboratories
    • Lab#SE00-1: Maven Person
    • Lab#SE00-2: Maven Clinic
    • Lab#SE00-3: Library Model
    • Lab#SE00-4: Abstract/Interface Human
    • Lab#SE01-1: Maven/Gradle Person and Account
    • Lab#SE01-2: Maven/Gradle Person and Account stored in JSON
    • Lab#SE02-1: Movie/Review, Model
    • Lab#SE02-2: Movie/Review, CRUD Operations
    • Lab#SE02-3: Movie/Review, factory
    • Lab#SE02-4: Movie/Review, interactivity and coupling
    • Lab#SE02-5: Movie/Review, simulate interactivity by console
    • Lab#SE03-1: Library/Book, Core-Model
    • Lab#SE03-2: Library/Book, Sprint Zero
    • Lab#SE03-3: Library/Book, Expand Model
    • Lab#SE04-1: healthyFood Restaurant, Core Model

    • Java SE readings
    • Java SE Resources
  • Python
    • Python Basics
    • Python: Basic Concepts
    • Python: Tips
  • JavaScript
    • JavaScript Basics
    • JavaScript: Basic Concepts
    • JavaScript: Tips
  • Spring
    • Spring Legacy
    • Spring Framework
    • Spring MVC
    • Springs Servlets

    • Spring Boot Basics
    • Spring Boot: fundamentals
    • Spring Boot: create a Project
    • Spring Boot: H2 DB and Thymeleaf
    • Spring Boot: cycle

    • Spring Boot Concepts
    • Spring Boot: Dependency Injection
    • Spring Boot: Annotations
    • Spring Boot: Controller
    • Spring Boot: View
    • Spring Boot: Thymeleaf
    • Spring Boot: Vaadin Flow
    • Spring Boot: Vaadin Hilla
    • Spring Boot: Model
    • Spring Boot: Rest
    • Spring Boot: Data & DB
    • Spring Boot: JPA & DI
    • Spring Boot: JPA Mappings
    • Spring Boot: JPA Relationships
    • Spring Boot: JPA Queries
    • Spring Boot: JPA Inherence
    • Spring Boot: Scaling

    • Spring Boot Laboratories
    • Lab#SB00-1: Library UML
    • Lab#SB00-2: CRUD User
    • Lab#SB00-3: LibraryManagement
    • Lab#SB00-4: API Rest
    • Lab#SB00-5: Rest & JPA-H2
    • Lab#SB00-6: Rest & MongoDB
    • Lab#SB00-7: Styling
    • Lab#SB01-1: DataBase
    • Lab#SB02-1: JPA Relationships
    • Lab#SB03-1: APIs & cloud
    • Lab#SB04-1: JPA Inherence
    • Lab#SB05-1: API Rest
    • Lab#SB06-1: employeeCourse
    • Lab#SB07-1: monitor Book
    • Lab#SB08-1: Restaurant UML
    • Lab#SB08-2: Vaadin
    • Lab#SB08-3: H2 and API Rest
    • Lab#SB08-4: JPA
    • Lab#SB08-5: Test API Rest
    • Lab#SB09-1: SpringIO Conference

    • Spring Boot readings
    • Spring Boot Resources
  • ReactJS
    • ReactJS: Principles
    • React JS: Introduction
    • React JS: render virtual DOM
    • React JS: Create a React project
    • React JS: Components
    • React JS: JSX
    • React JS: props and state

    • JavaScript: web scripting
    • JavaScript: basics
    • JavaScript: functions
    • JavaScript: objects
    • JavaScript: variables
    • JavaScript: flux control

    • ES6: ECMAScript 6
    • React JS ES6: arrow functions
    • React JS ES6: import modules
    • React JS ES6: array, data and key
    • React JS ES6: destructuring
    • React JS ES6: spread operator

    • ReacJS 18: Hooks
    • React JS: Rules of Hooks
    • ReactJS: useState
    • React JS: useReducer
    • React JS: useRef
    • React JS: useEffect
    • React JS: useContext
    • ReactJS: useMemo
    • ReactJS: custom hooks

    • ReactJS: Designing an App
    • React JS App: async
    • React JS App: events
    • React JS App: router
    • React JS App: conditional render
    • React JS App: styling

    • React JS: Laboratories
    • Lab#RE01-1: API Rest Axios
    • Lab#RE02-1: Router & Hooks
    • Lab#RE03-1: to-do app
    • Lab#RE03-2: HighCharts
    • Lab#RE03-3: API Rest Mono
    • Lab#RE03-4: API Rest Domains
    • Lab#RE03-5: data management
    • Lab#RE04-1: todo & server
    • Lab#RE04-2: Spring Boot & ReactJS
    • Lab#RE05-1: chat & websockets
    • Lab#RE05-2: chat: backend
    • Lab#RE05-3: chat & AWS
    • Lab#RE05-4: chat: test ws AWS
    • Lab#RE05-5: chat & front
    • Lab#RE05-6: chat & ws: front
    • Lab#RE06-1: healthyFood Restaurant
    • Lab#RE06-1-PR: create a pull request
    • Lab#RE07-1: traffic lights simulation

    • React JS readings
    • ReactJS Resources
  • Learning
    • Vocabulary
    • General Vocabulary
    • SCRUM Vocabulary
    • DevOps Vocabulary
    • Java SE Vocabulay
    • Spring Boot Vocabulary
    • DataBase Vocabulary
    • ReactJS Vocabulary
    • Web Vocabulary

    • Learning
    • Useful Questions
    • Learning: tips
    • Writing
    • Taking Notes
    • Comments
    • Document
    • Auto-Evaluate

    • Books & Articles
    • Books
    • Articles

    • What is SCRUM
    • SCRUM Agile Methodology
    • Agile Manifesto & Values
    • SCRUM Guide

    • Scrum Steps
    • Meetings, Impediments and Iterations
    • User stories, Tasks and Habits
    • Delivering Value & Communication
    • ScrumMaster, how it works
    • Mindset, the key to everything
    • Product Owner, how it works
    • Managing Time & Mind
    • Team & the Specialist
    • Albertus’ Dilemma
    • Before SCRUM
    • Team Dynamics
    • Emotions and Thoughts
    • Decision Making and Intuition
    • Beyond SCRUM
    • Balances, atmosphere and tools

    • Resources
    • SCRUM Resources
  • QGIS
    • QGIS basics
    • QGIS: basic concepts

    • QGIS laboratories
    • QGIS Laboratory 1: Introduction to Open Source GIS
  • ArcGIS Pro
    • ArcGIS Pro basics
    • ArcGIS Pro: basic concepts

    • ArcGIS Pro laboratories
    • ArcGIS Pro Laboratory 1: Getting Started
  • Bookmarks
    • Online Resources
    • Online Resources
  • About
    • About me and this site
    • About me
    • About this site
    • About images credit
  • Email
  • GitHub
  • LinkedIn
  1. React JS: Laboratories
  2. Lab#RE03-1: to-do app
  • ReactJS

  • ReactJS: Principles
    • React JS: Introduction
    • React JS: render virtual DOM
    • React JS: Create a React project
    • React JS: Components
    • React JS: JSX
    • React JS: props and state

  • JavaScript: web scripting
    • JavaScript: basics
    • JavaScript: functions
    • JavaScript: objects
    • JavaScript: variables
    • JavaScript: flux control

  • ES6: ECMAScript 6
    • React JS ES6: arrow functions
    • React JS ES6: import modules
    • React JS ES6: array, data and key
    • React JS ES6: destructuring
    • React JS ES6: spread operator

  • ReacJS 18: Hooks
    • React JS: Rules of Hooks
    • ReactJS: useState
    • React JS: useReducer
    • React JS: useRef
    • React JS: useEffect
    • React JS: useContext
    • ReactJS: useMemo
    • ReactJS: custom hooks

  • ReactJS: Designing an App
    • React JS App: async
    • React JS App: events
    • React JS App: router
    • React JS App: conditional render
    • React JS App: styling

  • React JS: Laboratories
    • Lab#RE01-1: API Rest Axios

    • Lab#RE02-1: Router & Hooks

    • Lab#RE03-1: to-do app
    • Lab#RE03-2: HighCharts
    • Lab#RE03-3: API Rest Mono
    • Lab#RE03-4: API Rest Domains
    • Lab#RE03-5: data management

    • Lab#RE04-1: todo & server
    • Lab#RE04-2: Spring Boot & ReactJS

    • Lab#RE05-1: chat & websockets
    • Lab#RE05-2: chat: backend
    • Lab#RE05-3: chat & AWS
    • Lab#RE05-4: chat: test ws AWS
    • Lab#RE05-5: chat & front
    • Lab#RE05-6: chat & ws: front

    • Lab#RE06-1: healthyFood Restaurant
    • Lab#RE06-1-PR: create a pull request

    • Lab#RE07-1: traffic lights simulation

  • React JS readings
    • ReactJS Resources

On this page

  • 1 user-story & mock-up
  • 2 step-by-step code
    • 2.1 Project creation
    • 2.2 create new todo
    • 2.3 read and render todo
    • 2.4 delete todo
    • 2.5 update chekbox todo
    • 2.6 update input todo
    • 2.7 useContext, useEffect, useRef todo
  • 3 Versions
  • Edit this page
  • Report an issue
  1. React JS: Laboratories
  2. Lab#RE03-1: to-do app

Lab#RE03-1: to-do app

ReactJS labs

reactjs
lab
Lab#RE03
labs
Author

albertprofe

Published

Tuesday, June 1, 2021

Modified

Sunday, August 10, 2025

📘 React JS Lab#RE03-1: to-do app

In this lab, we will be using:

  • the react-router-dom, which is a package with bindings for using React Router in web applications.
  • We will use the Semantic React library to paint some CSS.
    • We could use a table or list
  • We could use HighCharts to represent data.
  • Hooks we are going to use:
    • to create the basic app: useReducer, useContext,
    • to persist the state values between renders: useEffect, useRef.
    • to manage others states o variables: useState.

The lab will demonstrate how to use a react-router-dom with React to build a functional web application.


Reference:

  • codesanbox basic todo
  • codesanbox update handle function todo
  • codesanbox useContext todo

1 user-story & mock-up

This lab is a basic implementation of a Todo List application using React. It utilizes React hooks such as useReducer and useContext for state management.

We will define an initial set of todos and a reducer function that handles various actions like adding a new todo, deleting a todo, marking a todo as completed, and resetting the list.

Actions definition:

  • add action: Adds a new todo item to the list.
  • delete action: Removes a todo item from the list.
  • completed action: Toggles the completed status of a todo item.
  • reset action: Resets the todo list to its initial state.
const initialTodos = [
  {
    id: 1,
    text: "lean how to comunicate",
    completed: true,
    author: "Faby",
    due: 1 / 5 / 2022
  },
  {
    id: 2,
    text: "road out of hell",
    complete: false,
    author: "Alex",
    due: 1 / 6 / 2022
  }
];

The Object type represents one of JavaScript’s data types. It is used to store various keyed collections and more complex entities. Objects can be created using the Object() constructor or the object initializer / literal syntax.

Object

The TodoApp component uses the useReducer hook to manage the state of todos and dispatch actions based on user interactions. It renders a header, a button to create new todos, and a TodosList component that displays the list of todos.

inital render app

inital render app

calendar picker to set date

calendar picker to set date

creating new todos

creating new todos

2 step-by-step code

2.1 Project creation

step-by-step cheatsheet

step-by-step cheatsheet

First at all we create the React project with Route and Semantic css Library.

Then, the reducer component: <ToDoApp />.

It uses React’s useReducer hook to manage the state of the todo items. The initial todos are predefined, and the app supports actions like adding a new todo, deleting a todo, and marking a todo as completed. The state of the todos is stored in an array.

We crete a placeholder useReducer:

import { Button, Input, Checkbox } from "semantic-ui-react";
import { useReducer } from "react";

const initialTodos = [
  {
    id: 1,
    text: "lean how to comunicate",
    completed: true,
    author: "Faby",
    due: 1 / 5 / 2022
  },
  {
    id: 2,
    text: "road out of hell",
    complete: false,
    author: "Alex",
    due: 1 / 6 / 2022
  }
];

function reducer(state, action) {
  switch (action.type) {
    case "bla": {
      return;
    }
    case "blabla": {
      return;
    }
    default: {
      return state;
    }
  }};


export default function ToDoApp(){
    const [state, dispacher] = useReducer (reducer, initialTodos);

    return (
      <>
        <br />
        <span>ToDo</span>
        <Button>Delete</Button>
        <Input placeholder="Write something" />
        <Checkbox toggle />
        <br />
      </>
    );
};

2.2 create new todo

Step-by-step new todo creation:

  1. The <Button> component is rendered with an onClick event handler,
  2. when the button is clicked, it dispatches an action of type "add" using the dispatch function
  3. and calls the reducer.
  4. The reducer executes a case add creating a new state.
  5. As a new state is created,
  6. a new render is painted.

Highchart Pie example

Highchart Pie example
import { Button, Input, Checkbox } from "semantic-ui-react";
import { useReducer } from "react";

const initialTodos = [
  // todos objects
];

function reducer(state, action) {
  switch (action.type) {
     case "add": {
      return [
        ...state,
        {
          id: Date.now(),
          text: "",
          author: "",
          due: "",
          completed: false
        }
      ];
    }
    case "blabla": {
      return;
    }
    default: {
      return state;
    }
  }};


export default function ToDoApp(){
    const [state, dispatch] = useReducer(reducer, initialTodos);

    return (
      <>
      <div style={{margin: "40px"}}>        
        <br />
        <Button onClick={
          () => dispatch({ type: "add" })}>Create Todo</Button>
        <br />
        <span>todo id</span> {" "}
        <Button>Delete</Button>
        <Input placeholder="Write something" />
        <Checkbox toggle />
        <br />
        </div>

      </>
    );
};

The <Button> component is rendered with an onClick event handler. When the button is clicked, it dispatches an action of type "add" using the dispatch function and calls the reducer.

  <Button onClick={() => dispatch({ type: "add" })}>Create Todo</Button>

In the reducer, the spread operator (...state) is used to create a new array that includes all the existing elements without mutating the original state.

import { Button, Input, Checkbox } from "semantic-ui-react";
import { useReducer } from "react";

const initialTodos = [
  // todos objects
];

function reducer(state, action) {
  switch (action.type) {
     case "add": {
      return [
        ...state,
        {
          id: Date.now(),
          text: "",
          author: "",
          due: "",
          completed: false
        }
      ];
    }
    case "blabla": {
      return;
    }
    default: {
      return state;
    }
  }};


export default function ToDoApp(){
   // render
};

The spread operator (...state) is used to create a new array that includes all the elements from the existing state array. This is done to avoid mutating the original state.

A new object is created with the following properties:

  • id: A unique identifier generated using Date.now(). This will ensure that each new item has a unique identifier.
  • text: An empty string.
  • author: An empty string.
  • due: An empty string.
  • completed: A boolean value set to false, indicating that the item is not completed.

The new object is then added to the end of the new array created at initial load using the spread operator (…state).

This ensures that the new item is appended to the existing items in the state array.

Finally, the updated array is returned from the reducer function, representing the new state with the newly added item.

2.3 read and render todo

import React, { useReducer } from "react";

const initialTodos = [
  // todos initial
];

function appReducer(state, action) {
  switch (action.type) {
    // cases
}

export default function TodoApp() {
  const [state, dispatch] = useReducer(appReducer, initialTodos);

  return (
    <>
      <h3>List: add, delete, complete and refresh</h3>
      <button onClick={() => dispatch({ type: "add" })}>
        Create Todo
      </button>{" "}
      <button>Clear Todo</button>
      <br /> <br />
      <div style={{ margin: "20px" }}>
        {state.map((item) => (
          <>
            <input type="checkbox"/>
            <input type="text" defaultValue={item.text} />{" "}
            <input type="text" defaultValue={item.author} />{" "}
            <input type="date" defaultValue={item.due} />{" "}
            <button>
              Delete
            </button>
            <br />
          </>
        ))}
      </div>
    </>
  );
}

We are going to map over our state and generating a list of htmml elements based on its contents.

Mozilla map docs

Within the mapping function, each item in the state array is rendered as a set of elements enclosed within an empty fragment (<>...</>).

(<>...</>): this is a common technique in React to group multiple elements without adding unnecessary wrapper elements to the DOM.

For each item in the state array, the code generates the following elements:

  • <input type="checkbox">: This is a checkbox input element.
    • The checked attribute is bound to the item.completed property, which presumably determines whether the checkbox should be checked or not.
  • <input type="text">: Two text input elements are rendered, each with the defaultValue attribute bound:
    • to item.text and
    • item.author respectively.
    • These inputs display the default values of the corresponding text and author properties of the item object.
  • <input type="date">: This is a date input element with the defaultValue attribute bound to item.due.
    • It displays the default due date value of the item object.
  • <button>: A button element is rendered with the label “Delete”.

2.4 delete todo

We define the operation delete:

  • event onClick on button
  • case delete on reducer
  • reducer creates new state which triggers new render with new state

The button element, when clicked, triggers an action to delete an item. It uses an onClick event handler that dispatches a “delete” action with the item’s ID as the payload, allowing the application to handle the deletion logic based on the dispatched action.

  <Button
    onClick={() => dispatch({ type: "delete", payload: item.id })}>
    Delete
  </Button>

The reducer case statement for handling the “delete” action filters the state array based on the item’s ID, removing the item with the matching ID from the state.

function appReducer(state, action) {
  switch (action.type) {
    //.. other cases

    case "delete": {
      return state.filter((item) => item.id !== action.payload);
    }
    
    //.. other cases  
  }
}

2.5 update chekbox todo

NoteJSX elements directly inside a map() call always need keys!

Keys tell React which array item each component corresponds to, so that it can match them up later. This becomes important if your array items can move (e.g. due to sorting), get inserted, or get deleted. A well-chosen key helps React infer what exactly has happened, and make the correct updates to the DOM tree.

Rendering Lists - Why does React need keys?

For example, React.Fragment and a key for our list:

{state.map((item) => (
      <React.Fragment key={item.id}>
        
      </React.Fragment>
))}

We could update the complete field by using a event onChange that dispatchs as a payload the item.id with the completed type:

 <input
    type="checkbox"
    checked={item.completed}
    onChange={
      () => dispatch({ type: "completed", payload: item.id })}
/>

And the reducer with the completed action:

function appReducer(state, action) {
  switch (action.type) {
    // other cases
    case "completed": {
      return state.map((item) => {
        if (item.id === action.payload) {
          return {
            ...item,
            completed: !item.completed
          };
        }
        return item;
      });
    }
    // default case
}

2.6 update input todo

We could update the input common fields -text, author, due- by creating a handler function handleUpdate:

const handleUpdate = (id, field, value) => {
    dispatch({
      type: "update",
      payload: {
        id,
        field,
        value
      }
    });
};

The inputs onChange, now, will call the handleUpdate function with the field:

<input
  type="text"
  value={item.text}
  onChange={(e) => handleUpdate(item.id, "text", e.target.value)}
/>{" "}
<input
  type="text"
  value={item.author}
  onChange={(e) => handleUpdate(item.id, "author", e.target.value)}
/>{" "}
<input
  type="date"
  value={item.due}
  onChange={(e) => handleUpdate(item.id, "due", e.target.value)}
/>{" "}

And the reducer with the update action:

function appReducer(state, action) {
  switch (action.type) {
    // other cases
    case "update": {
      const { id, field, value } = action.payload;
      return state.map((item) => {
        if (item.id === id) {
          return {
            ...item,
            [field]: value
          };
        }
        return item;
      });
    }
    // default case
}

An object initializer is a comma-delimited list of zero or more pairs of property names and associated values of an object, enclosed in curly braces {}.

const { id, field, value } = action.payload;

Object_initializer

2.7 useContext, useEffect, useRef todo

The useEffect, useRef, and useContext hooks are used to handle different aspects of state management and render lifecycle.

  • useEffect: is used to update the stateRef.current value whenever the state changes.
    • It ensures that the stateRef always holds the latest value of state.
    • The effect is triggered whenever the state dependency changes, which means it will run after every state update.
  • useRef: the stateRef variable is created using useRef. It creates a mutable reference that persists across renders.
    • stateRef is used to hold the current value of state.
    • By using useRef, the value can be updated without causing a re-render, and it can be accessed inside the useEffect hook.
  • useContext: the Context is created using React.createContext(), and it is used to share the dispatch function with child components.
    • By wrapping the components inside <Context.Provider value={dispatch}>, the dispatch function is made available to all components within the Context.Provider scope.
    • The child component, TodosList, accesses the dispatch function using the useContext hook.
function appReducer(state, action) {
  // ---
}

const Context = React.createContext();


export default function TodoApp() {
  const [state, dispatch] = useReducer(appReducer, initialTodos);
  const stateRef = useRef(state);

  useEffect(() => {
    stateRef.current = state;
  }, [state]);

  return (
    <Context.Provider value={dispatch}>
      <h3>List: add, delete, complete and refresh</h3>
      <button onClick={
        () => dispatch({ type: "add" })}>Create Todo</button>
      <br />
      <br />
      <TodosList items={stateRef.current} />
    </Context.Provider>
  );
}

function TodosList({ items }) {
  return items.map((item) => <TodoItem key={item.id} {...item} />);
}

}

function TodoItem({ id, completed, author, text, due }) {
  const dispatch = useContext(Context);
  //..
}

3 Versions

Code Version Commit Folder-Tree Screeshoots
todoApp 0.0 create project with route: todoApp 0.0 initial tree-folder render home
todoApp 0.1 create new todo: todoApp 0.1 - initial render - todo created render
todoApp 0.2 render todos, clear, delete todo: todoApp 0.2 - initial render - todo created render
Back to top
Lab#RE03-2: HighCharts

This website is built with Quarto.

Difficulties are just things to overcome, after all. Ernest Shackleton

  • Edit this page
  • Report an issue