Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

Sorry, you do not have permission to ask a question, You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please type your username.

Please type your E-Mail.

Please choose an appropriate title for the post.

Please choose the appropriate section so your post can be easily searched.

Please choose suitable Keywords Ex: post, video.

Browse

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

Querify Question Shop: Explore Expert Solutions and Unique Q&A Merchandise

Querify Question Shop: Explore Expert Solutions and Unique Q&A Merchandise Logo Querify Question Shop: Explore Expert Solutions and Unique Q&A Merchandise Logo

Querify Question Shop: Explore Expert Solutions and Unique Q&A Merchandise Navigation

  • Home
  • About Us
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • About Us
  • Contact Us
Home/ Questions/Q 3751

Querify Question Shop: Explore Expert Solutions and Unique Q&A Merchandise Latest Questions

Author
  • 61k
Author
Asked: November 26, 20242024-11-26T05:37:08+00:00 2024-11-26T05:37:08+00:00

Understanding CRUD operations with a note app in react

  • 61k

This post is use to demonstrate the use of CRUD operations in react using react.
CRUD stands for create/read/update/delete.
We also learn the following

  • Persist data using local storage
  • debouncing
  • props
  • hooks
  • Date formatter function

Following is the structure of the app

Image description

This app has 3 components Sidebar, Note Container, Notes.
App component will be the main component/parent component. All the signals pass through this component only. In another words all the children component talk to each other through app component.

First Lets create the bere bone of the project

SideBar Js

  import React from 'react' import './Sidebar.css'  export default function Sidebar() {      return (         <h1>Sidebar</h1>     ) }    
Enter fullscreen mode Exit fullscreen mode

SideBar css

  .sidebar-container {     height: 100%;     width: 10%;     display: flex;     flex-direction: column;     align-items: center; }  svg {     margin-bottom: 10px; }  ul>li {     height: 30px;     width: 30px;     border-radius: 50%;     margin: 5px;     list-style: none; }   
Enter fullscreen mode Exit fullscreen mode

Note Container js

  import React from 'react' import './NoteContainer.css'  export default function NoteContainer() {      return (         <h1>Note Container</h1>     ) }   
Enter fullscreen mode Exit fullscreen mode

Note Container css

  .note-container {     height: 100%; }  .header {     margin-bottom: 2rem; }  .note-body {     display: flex;     flex-wrap: wrap;     gap: 20px;     overflow: auto;     height: 90%; }   
Enter fullscreen mode Exit fullscreen mode

Notes Js

  import React from 'react' import './Note.css' function Note() {      return (         <h1>Notes</h1>     ) } export default Note   
Enter fullscreen mode Exit fullscreen mode

Notes css

  .card-container {     height: 300px;     width: 250px;     border-radius: 1rem; }  .text-area {     width: 100%;     height: 80%;     border: none;     outline: none;     resize: none;     line-height: 1.875rem;     padding: 1rem;     background-color: transparent; }  .footer {     display: flex;     align-items: center;     justify-content: space-around; }   
Enter fullscreen mode Exit fullscreen mode

App js

   import './App.css'; function App() {    return (     <div className="App">       <Sidebar />       <NoteContainer />     </div>   ); }  export default App;   
Enter fullscreen mode Exit fullscreen mode

App css

  * {   margin: 0;   padding: 0;   box-sizing: border-box; }  .App {   height: 100vh;   display: flex; }  .custom-scroll::-webkit-scrollbar {   width: 8px; }  .custom-scroll::-webkit-scrollbar-track {   background-color: transparent; }  .custom-scroll::-webkit-scrollbar-thumb {   border-radius: 20px;   background-color: lightgray;   transition: 300ms; }  .custom-scroll::-webkit-scrollbar-thumb:hover {   background-color: gray; }   
Enter fullscreen mode Exit fullscreen mode

First lets create the sidebar

  import React from 'react' import './Sidebar.css'  export default function Sidebar() {   const color = ['#fe9b72', '#fec971', "#00d4fe", '#b693fd', '#e4ee91']     const [open, setOpen] = useState(false);      return (         <div className='sidebar-container'>             <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth="1.5" stroke="currentColor" class="w-6 h-6" height='100' width='100'  onClick={() => setOpen(!open)}>                 <path stroke-linecap="round" stroke-linejoin="round" d="M12 9v6m3-3H9m12 0a9 9 0 11-18 0 9 9 0 0118 0z" />             </svg>             {open &&                 <ul>                     {color.map((item, index) => <li key={index} style={{ background: item }} onClick={() => props.addnotes(item)}></li>)}                 </ul>             }         </div>     ) }   
Enter fullscreen mode Exit fullscreen mode

Wow! What just happened. I know that's a lot to process. Don't worry I'll walk you through this. Oh! also keep your eyes open you might find some useful code snippet along the way that you use again and again almost in every project 😉.

Now lets see the jsx first.

I did nothing fancy hear just created a parent div with class sidebar-container. See css above in starting. Then added a svg image to show icon. That's it.

If you look closely 🧐, you might see a onClick() function in svg tag. What does it do you might ask.

  constt [open, setOpen] => useState(false);  <svg onClick ={() => setOpen(!open)}   
Enter fullscreen mode Exit fullscreen mode

Well all it does it toggle the div or image or whatever you want to toggle. Like on/off the light. Think as you want something to render on screen only when click on a button and then disappear when you click again. Well this function do the trick. When you click on the button with which we attached this function, it toggles the state from true to false or vice versa.

Now your second question might be what the duck is

  {open &&                 <ul>                     {color.map((item, index) => <li key={index} style={{ background: item }} onClick={() => props.addnotes(item)}></li>)}                 </ul>             }   
Enter fullscreen mode Exit fullscreen mode

This is nothing but a way to tell the computer if state is true render that ul tag else do not render. This is called conditional rendering in world of react and && operator will be used to implement this magic. You can achieve this using class as shown below. Also I am using array of different colors which are mapped as a li list. This will used to produce notes component of different color.

  <ul className={`sidebar_list ${open ? 'sidebar_list_active' : ''} `}>                 {                     color.map((item, index) => <li className='sidebar_list_item' key={index} style={{ backgroundColor: item }} onClick={() => props.addNotes(item)} />)                 }             </ul>   
Enter fullscreen mode Exit fullscreen mode

You also need a pinch of css here to make it work. Note that classname are not same because it was copied from other project.

   .sidebar {     display: flex;     flex-direction: column;     gap: 40px; }  .sidebar svg {     cursor: pointer; }  .sidebar_list {     display: flex;     flex-direction: column;     gap: 20px;     align-items: center;     height: 0; }  .sidebar_list_active {     height: 300px; }   .sidebar_list_item {     list-style-type: none;     height: 26px;     width: 26px;     border-radius: 50%; }   
Enter fullscreen mode Exit fullscreen mode

Wallah! Done and Dustin. See the preview below

Image description

Lets structure Notes component first

All I am doing is structure the jsx to see how it looks like. Remember it is very important to fist create the design and fill it with dummy data. It will be easier to imagine the solution.

  import React from 'react' import './Note.css' function Note() {      return (         <div className='card-container' style={{ backgroundColor: 'cyan' }}>             <textarea className='text-area' defaultValue={'asdasdsadas'}</textarea>             <div className='footer'>                 <p> 16:26 PM 01 Nov</p>                 <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-6 h-6" height='25' width='25'>                     <path stroke-linecap="round" stroke-linejoin="round" d="M14.74 9l-.346 9m-4.788 0L9.26 9m9.968-3.21c.342.052.682.107 1.022.166m-1.022-.165L18.16 19.673a2.25 2.25 0 01-2.244 2.077H8.084a2.25 2.25 0 01-2.244-2.077L4.772 5.79m14.456 0a48.108 48.108 0 00-3.478-.397m-12 .562c.34-.059.68-.114 1.022-.165m0 0a48.11 48.11 0 013.478-.397m7.5 0v-.916c0-1.18-.91-2.164-2.09-2.201a51.964 51.964 0 00-3.32 0c-1.18.037-2.09 1.022-2.09 2.201v.916m7.5 0a48.667 48.667 0 00-7.5 0" />                 </svg>             </div>         </div>     ) } export default Note   
Enter fullscreen mode Exit fullscreen mode

This will show like this

Image description

Now that we see the design we can imagine how data will come in this jsx. Structure of data should be like below

  { text: 'ssasdasda', time: '16:26 PM 01 Nov',   
Enter fullscreen mode Exit fullscreen mode

Structure Note Container component

  import React from 'react' import Note from '../Note/Note' import './NoteContainer.css'  export default function NoteContainer(props) {       return (         <div className='note-container'>             <h1 className='header'>Notes</h1>             <div className='note-body custom-scroll'>                 <Note/>             </div>         </div>     ) }    
Enter fullscreen mode Exit fullscreen mode

Notice that we are calling the Notes component in Note Container. All the notes will leave in Notes Container.

Now that the basic image is clear. We will work with dummy data and functionality along the way. I am gonna demonstrate how data travel through component in react. Remember , It is very important to understand props and states in react as it's the basic of mostly all react apps. I will also demonstrate how data propagate from children to parent in react. This is very important concept to learn. You must have clarity on callbacks in js.

Demonstration of props with dummy data

   import './App.css'; import NoteContainer from './components/NoteContainer/NoteContainer'; import Sidebar from './components/Sidebar/Sidebar'; import { useState, useEffect } from 'react'  function App() { const notes=[  {       text: 'vdscmdscdc',       time: '4.37 PM',       color: 'yellow'     },     {       text: 'vdscmdscdc',       time: '4.37 PM',       color: 'pink'     },     {       text: 'vdscmdscdc',       time: '4.37 PM',       color: 'orange'     },     {       text: 'vdscmdscdc',       time: '4.37 PM',       color: 'seagreen'     }]    return (     <div className="App">       <Sidebar />       <NoteContainer notes={notes} />     </div>   ); }  export default App;   //----notes array will send to note container as props--- import React from 'react' import Note from '../Note/Note' import './NoteContainer.css'  export default function NoteContainer(props) {      return (         <div className='note-container'>             <h1 className='header'>Notes</h1>             <div className='note-body custom-scroll'>                <Note notes={props.notes} />             </div>         </div>     ) }  //----from notes-container to notes data will travel---  import React from 'react' import './Note.css' function Note(props) {     return (         <div className='card-container' style={{ backgroundColor: props.notes.color }}>             <textarea className='text-area' defaultValue= {props.notes.text}></textarea>             <div className='footer'>                 <p> {props.notes.time}</p>                 <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-6 h-6" height='25' width='25'>                     <path stroke-linecap="round" stroke-linejoin="round" d="M14.74 9l-.346 9m-4.788 0L9.26 9m9.968-3.21c.342.052.682.107 1.022.166m-1.022-.165L18.16 19.673a2.25 2.25 0 01-2.244 2.077H8.084a2.25 2.25 0 01-2.244-2.077L4.772 5.79m14.456 0a48.108 48.108 0 00-3.478-.397m-12 .562c.34-.059.68-.114 1.022-.165m0 0a48.11 48.11 0 013.478-.397m7.5 0v-.916c0-1.18-.91-2.164-2.09-2.201a51.964 51.964 0 00-3.32 0c-1.18.037-2.09 1.022-2.09 2.201v.916m7.5 0a48.667 48.667 0 00-7.5 0" />                 </svg>             </div>         </div>     ) } export default Note    
Enter fullscreen mode Exit fullscreen mode

Functionality to create new notes

Image description

So we have to send signal from sidebar to notes component to create new note. App component will be the mediator. You will learn how child component send signals to parent component.

  import './App.css'; import NoteContainer from './components/NoteContainer/NoteContainer'; import Sidebar from './components/Sidebar/Sidebar'; import { useState, useEffect } from 'react'  function App() { const [notes, setNotes] = useState([  {       text: 'vdscmdscdc',       time: '4.37 PM',       color: 'yellow'     },     {       text: 'vdscmdscdc',       time: '4.37 PM',       color: 'pink'     },     {       text: 'vdscmdscdc',       time: '4.37 PM',       color: 'orange'     },     {       text: 'vdscmdscdc',       time: '4.37 PM',       color: 'seagreen'     }])  const addNotes = (color) => { const tempNotes = [...notes];  tempNotes.push({ id: Date.now(), text: '', time: Date.now(); color, })  setNotes(tempNotes); }    return (     <div className="App">       <Sidebar addNotes={addNotes}/>       <NoteContainer notes={notes} />     </div>   ); }   
Enter fullscreen mode Exit fullscreen mode

We will get this function as props in sidebar component

Image description

Lets understand the functionality by an image

Image description

I'm hoping this image help you to understand what's going on here.
I'll first wrap this in bullets.

  • Create a add function in app component.
  • This component will return a object which will added to the main array of notes, which is stored in state.
  • This array is traveling to the Note container component and note container sending this data to Notes component.
  • Notes component fetching required data from array and feeding to the designated design field. I hope you get the idea.

Functionality to delete a note

Image description

Delete from ui is very simple. Believe it or not it just a one liner.

  import './App.css'; import NoteContainer from './components/NoteContainer/NoteContainer'; import Sidebar from './components/Sidebar/Sidebar'; import { useState, useEffect } from 'react'  function App() { const [notes, setNotes] = useState([  {       text: 'vdscmdscdc',       time: '4.37 PM',       color: 'yellow'     },     {       text: 'vdscmdscdc',       time: '4.37 PM',       color: 'pink'     },     {       text: 'vdscmdscdc',       time: '4.37 PM',       color: 'orange'     },     {       text: 'vdscmdscdc',       time: '4.37 PM',       color: 'seagreen'     }])  const addNotes = (color) => { const tempNotes = [...notes]; tempNotes.push({ id: Date.now(), text: '', time: Date.now(); color, }) setNotes(tempNotes); }  const deleteNote = id => {   //You can use two method to delete element   // array filter method or array slice method   tempNotes = [...notes];   setNotes(tempNotes.filter(note => note.id !== id);   /*   using slicemethod   const index = tempNotes.findIndex(note => note.id === id);   if(!index) return;   setNotes(tempNotes.slice(index,1));   */ }    return (     <div className="App">       <Sidebar addNotes={addNotes}/>       <NoteContainer notes={notes} deleteNotes={deleteNotes}/>     </div>   ); }  //----------Note container will get delete function as props and send it to Notes component  import React from 'react' import Note from '../Note/Note' import './NoteContainer.css'  export default function NoteContainer(props) {      return (         <div className='note-container'>             <h1 className='header'>Notes</h1>             <div className='note-body custom-scroll'>                 {                     props.notes.length > 0 ? notes.map((item) => (                         <Note key={item.id} note={item} deleteNote={props.deleteNote}                              />                     )) : <h1>Empty Notes</h1>                 }             </div>         </div>     ) }  //--------deleteNote function pass to the delete icon as callback function  import React from 'react' import './Note.css' function Note(props) {        return (         <div className='card-container' style={{ backgroundColor: props.note.color }}>             <textarea className='text-area' defaultValue={props.note.text} onChange={e => updateText(e.target.value, props.note.id)}></textarea>             <div className='footer'>                 <p>{props.note.time}</p>                 <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-6 h-6" height='25' width='25' onClick={() => props.deleteNote(props.note.id)}>                     <path stroke-linecap="round" stroke-linejoin="round" d="M14.74 9l-.346 9m-4.788 0L9.26 9m9.968-3.21c.342.052.682.107 1.022.166m-1.022-.165L18.16 19.673a2.25 2.25 0 01-2.244 2.077H8.084a2.25 2.25 0 01-2.244-2.077L4.772 5.79m14.456 0a48.108 48.108 0 00-3.478-.397m-12 .562c.34-.059.68-.114 1.022-.165m0 0a48.11 48.11 0 013.478-.397m7.5 0v-.916c0-1.18-.91-2.164-2.09-2.201a51.964 51.964 0 00-3.32 0c-1.18.037-2.09 1.022-2.09 2.201v.916m7.5 0a48.667 48.667 0 00-7.5 0" />                 </svg>             </div>         </div>     ) } export default Note   
Enter fullscreen mode Exit fullscreen mode

Also I added the conditional rendering in Note container component. If the length of the notes array is greater then 0 it will show notes else it will show 'Empty Notes' massage.

Image description

Persist Notes and text in local storage and update text

Also this includes format data, useEffect hooks, debounce **
**Plz write your queries in comments

  //App  import './App.css'; import NoteContainer from './components/NoteContainer/NoteContainer'; import Sidebar from './components/Sidebar/Sidebar'; import { useState, useEffect } from 'react'  function App() {    const [notes, setNotes] = useState(JSON.parse(localStorage.getItem('note-app')) || [])    const addnotes = (color) => {     const tempNotes = [...notes];     tempNotes.push({       id: Date.now() + '' + Math.floor(Math.random() * 78),       text: '',       time: Date.now(),       color     })      setNotes(tempNotes);   }    const deleteNote = (id) => {     const tempNotes = [...notes];     // const index = tempNotes.findIndex(item => item.id === id);     // if(index <=0) return     //setNotes(tempNotes.splice(index,1))     setNotes(tempNotes.filter(item => item.id !== id));   }    useEffect(() => {     localStorage.setItem('note-app', JSON.stringify(notes));   })    const updateText = (text, id) => {     const tempNotes = [...notes];     const index = tempNotes.findIndex(item => item.id === id);     if (index <= 0) return     tempNotes[index].text = text;     setNotes(tempNotes);   }    return (     <div className="App">        <Sidebar addnotes={addnotes} />       <NoteContainer notes={notes} deleteNote={deleteNote} updateText={updateText} />      </div>   ); } export default App;  //Sidebar import React, { useState } from 'react' import './Sidebar.css'  export default function Sidebar(props) {     const color = ['#fe9b72', '#fec971', "#00d4fe", '#b693fd', '#e4ee91']     const [open, setOpen] = useState(false);      return (         <div className='sidebar-container'>             <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth="1.5" stroke="currentColor" class="w-6 h-6" height='100' width='100' onClick={() => setOpen(!open)}>                 <path stroke-linecap="round" stroke-linejoin="round" d="M12 9v6m3-3H9m12 0a9 9 0 11-18 0 9 9 0 0118 0z" />             </svg>             {open &&                 <ul>                     {color.map((item, index) => <li key={index} style={{ background: item }} onClick={() => props.addnotes(item)}></li>)}                 </ul>             }         </div>     ) }  //Note Container import React from 'react' import Note from '../Note/Note' import './NoteContainer.css'  export default function NoteContainer(props) {      const reverseArray = (arr) => {         const array = [];         for (let i = arr.length - 1; i >= 0; i--) {             array.push(arr[i]);         }         return array     }      const notes = reverseArray(props.notes)      return (         <div className='note-container'>             <h1 className='header'>Notes</h1>             <div className='note-body custom-scroll'>                 {                     notes.length > 0 ? notes.map((item) => (                         <Note key={item.id} note={item} deleteNote={props.deleteNote}                             updateText={props.updateText} />                     )) : <h1>Empty Notes</h1>                 }             </div>         </div>     ) }   // Notes  import React from 'react' import './Note.css' function Note(props) {      const formatDate = (value) => {         if (!value) return;         const date = new Date(value);         const monthsName = ['Jan', 'Feb', 'March', 'April', 'May', 'June', 'July', 'Aug', 'Sept', 'Oct', 'Nov', 'Dec'];          let hrs = date.getHours();         let amPm = hrs > 12 ? 'PM' : 'AM';         hrs = hrs ? hrs : '12';         hrs = hrs > 24 ? hrs - 12 : hrs;          let min = date.getMinutes();         min = min < 10 ? '0' + min : min;          let day = date.getDate();         day = day < 10 ? '0' + day : day;         const month = monthsName[date.getMonth()];          return `${hrs}:${min} ${amPm} ${day} ${month}`;     };      let timer = 500, timeout;     const debounce = (fun) => {         clearTimeout(timeout);         timeout = setTimeout(fun, timer);     }       const updateText = (text, id) => {         debounce(() => props.updateText(text, id))     };      return (         <div className='card-container' style={{ backgroundColor: props.note.color }}>             <textarea className='text-area' defaultValue={props.note.text} onChange={e => updateText(e.target.value, props.note.id)}></textarea>             <div className='footer'>                 <p>{formatDate(props.note.time)}</p>                 <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-6 h-6" height='25' width='25' onClick={() => props.deleteNote(props.note.id)}>                     <path stroke-linecap="round" stroke-linejoin="round" d="M14.74 9l-.346 9m-4.788 0L9.26 9m9.968-3.21c.342.052.682.107 1.022.166m-1.022-.165L18.16 19.673a2.25 2.25 0 01-2.244 2.077H8.084a2.25 2.25 0 01-2.244-2.077L4.772 5.79m14.456 0a48.108 48.108 0 00-3.478-.397m-12 .562c.34-.059.68-.114 1.022-.165m0 0a48.11 48.11 0 013.478-.397m7.5 0v-.916c0-1.18-.91-2.164-2.09-2.201a51.964 51.964 0 00-3.32 0c-1.18.037-2.09 1.022-2.09 2.201v.916m7.5 0a48.667 48.667 0 00-7.5 0" />                 </svg>             </div>         </div>     ) } export default Note     
Enter fullscreen mode Exit fullscreen mode

javascriptreacttutorialwebdev
  • 0 0 Answers
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

Sidebar

Ask A Question

Stats

  • Questions 4k
  • Answers 0
  • Best Answers 0
  • Users 2k
  • Popular
  • Answers
  • Author

    ES6 - A beginners guide - Template Literals

    • 0 Answers
  • Author

    Understanding Higher Order Functions in JavaScript.

    • 0 Answers
  • Author

    Build a custom video chat app with Daily and Vue.js

    • 0 Answers

Top Members

Samantha Carter

Samantha Carter

  • 0 Questions
  • 20 Points
Begginer
Ella Lewis

Ella Lewis

  • 0 Questions
  • 20 Points
Begginer
Isaac Anderson

Isaac Anderson

  • 0 Questions
  • 20 Points
Begginer

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help

Footer

Querify Question Shop: Explore Expert Solutions and Unique Q&A Merchandise

Querify Question Shop: Explore, ask, and connect. Join our vibrant Q&A community today!

About Us

  • About Us
  • Contact Us
  • All Users

Legal Stuff

  • Terms of Use
  • Privacy Policy
  • Cookie Policy

Help

  • Knowledge Base
  • Support

Follow

© 2022 Querify Question. All Rights Reserved

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.