1. Initialize notes
The following code completes these operations:
- Call
("notes")
Get data named "notes" from the browser's local storage. - use
Parses the obtained string into an array.
- If there is no "notes" data in the local storage (return value is null), notes are set to an empty array [] by default.
const [notes, setNotes] = ( (("notes")) || [] )
useState hook
useState is a hook for React that introduces state in function components.
It returns an array with two elements:
- Current status value (here is notes).
- A function that updates the state (here is setNotes).
localStorage
-
localStorage
Is a browser-provided API for storing key-value pair data locally. -
("notes")
fromlocalStorage
Get the key in "notes
” data, the result returned is a string.
-
localStorage
All data stored in it is a string. -
Parses strings into JavaScript objects.
If the stored data is a JSON string, for example: "[1, 2, 3]", callThen you will get [1, 2, 3].
|| Operator
- || is a logic or operator that provides a default value.
- if
("notes")
Returns null (that is, the "notes" key is not found),(("notes"))
The result will be null. - In this case, the right side of the expression ([]) is returned, indicating that the initial value of notes is an empty array.
2. Save notes to localStorage every time the notes change
(() => { ("notes", (notes)) }, [notes])
useEffect
is a hook for React that handles side effects in function components.
- Side effects usually refer to behaviors that are not related to component rendering logic, such as: data acquisition, subscription, manual DOM operations, or logging, etc.
Its syntax is as follows:
(effectFunction, dependencies);
effectFunction
is a function that runs under certain conditions.dependencies
is an array, controleffectFunction
run time.
is an API provided by the browser to
localStorage
Store key-value pairs in it.
It accepts two parameters:
- Key: The name of the stored data (here is "notes").
- Value: The specific data stored must be a string.
(notes)
:
- Convert notes to strings in JSON format because
localStorage
Only string data can be stored.
When the component renders and the notes change:
- useEffect will be triggered.
- ("notes", (notes)) Save the latest notes array to local storage.
If notes have not changed:
- Even if the component is re-rendered, useEffect will not run because the value of notes has not changed.
3. What is Lazy State Initialization?
Normally, the initial value of useState is calculated directly:
const [state, setState] = (computeInitialState());
- here
computeInitialState()
Will be executed immediately every time the component is rendered, even if the result only needs to be used during the initial render. - if
computeInitialState
It is a complex calculation function that will waste performance.
To solve this problem, React provides a lazy initialization method: by passing a function to useState instead of passing the calculation result directly. This function is only executed when the component is rendered for the first time and will not be called again afterwards.
Lazy initialization
const [state, setState] = (() => computeInitialState());
- When passing a function to useState, React will only call this function when the component is first rendered to calculate the initial state.
- This function will no longer be called in subsequent state updates.
4. Implement the operation of deleting notes in React
<button className="delete-btn" onClick={(event) => (event, )} > <i className="gg-trash trash-icon"></i> </button>
<button>
element
- HTML button labels that define a clickable interactive element.
- In React, events and custom properties can be bound and related event handlers can be triggered.
In the callback function(event) => (event, )
is an arrow function, called during executionmethod, and pass two parameters to it:
-
event
: Native click event object, providing information about clicks (such as target element, mouse position, etc.). -
: The unique identifier of the current note, used to specify the specific note to be deleted.
<i>
is an inline element of HTML and is usually used as a placeholder for an icon.
function deleteNote(event, noteId){ () setNotes(oldNotes => (note => !== noteId)) }
()
effect:
- Blocks events from propagating from the current element to the parent element or other ancestor elements (i.e. prevents events from bubbled).
- Prevents the click event of the delete button from triggering other event handling logic of the parent component (such as click event of the entire note item).
Examples of scenarios:
Suppose the outer component of the note item has a click event binding:
<div onClick={() => ("Note clicked!")}> <button onClick={(event) => deleteNote(event, noteId)}>Delete</button> </div>
If not()
:
- When you click the delete button, it will be triggered
deleteNote
, it will trigger the outer layerdiv
ofonClick
。
Have it()
:
- When you click the delete button, it will only trigger
deleteNote
。
Arrow function oldNotes => (...)
setNotes
Receive an update function whose parameters are the current state valueoldNotes
。
filter method:
- Returns a new array containing all elements that meet the criteria.
- Condition: Keep notes whose id does not equal noteId, that is, delete the notes corresponding to noteId.
Complete logic
Iterate through the oldNotes array via filter:
- If !== noteId, the note is retained.
- If === noteId, the note is filtered out.
The returned new array is assigned to notes and triggers component re-rendering.
5. CSS implementation of delete button
.delete-btn { display: none; background: none; border: none; }
effect
- Defines the initial style of the delete button, which is hidden by default.
Attribute explanation
- display: none;:
Hide elements, buttons do not occupy layout space and are not visible.
- background: none;:
Removes the default background style of the button.
- border: none;:
Removes the default border of the button.
.title:hover > .delete-btn { display: block; }
effect
- When the user hovers over the .title element, its child element .delete-btn is displayed.
Attribute explanationdisplay: block;
:
Make .delete-btn visible and displayed as block-level elements.
> .delete-btn
:
- Indicates that only the direct child element .delete-btn is selected to avoid affecting other deeper nested .delete-btn.
Implementation logic
By pseudo-class:hover
, dynamically switch the display status of the button to provide a better user interaction experience.
.trash-icon { cursor: pointer; }
effect
- Defines the style of the trash can icon so that it has a click effect when the user hovers the mouse.
Attribute explanationcursor: pointer;
:
A hand pointer is displayed when the mouse is hovering, indicating that the element is clickable.
.gg-trash { box-sizing: border-box; position: relative; display: block; transform: scale(var(--ggs,1)); width: 10px; height: 12px; border: 2px solid transparent; box-shadow: 0 0 0 2px, inset -2px 0 0, inset 2px 0 0; border-bottom-left-radius: 1px; border-bottom-right-radius: 1px; margin-top: 4px; }
effect
- Defines the appearance of the trash can icon, including size, shape, and overall style.
Attribute explanationbox-sizing: border-box;
:
- Controls the width and height calculation method of elements, including inner margins and borders.
position: relative;
:
- Define elements as relative positioning, used to match the absolute positioning of child elements.
transform: scale(var(--ggs,1));
:
- Use the CSS variable --ggs to control the scaling, defaulting to 1.
width: 10px; height: 12px;
:
- Defines the width and height of the trash can.
border: 2px solid transparent;
:
Set transparent borders.
box-shadow
:
Add outer and inner borders to trash can shapes:
- 0 0 0 2px: External border, 2px wide.
- inset -2px 0 0 and inset 2px 0 0: Internal partitions.
border-bottom-left-radius
andborder-bottom-right-radius
:
- Add rounded corners to the two corners at the bottom of the trash can.
margin-top: 4px;
:
Add spacing to the top.
.gg-trash::after { background: currentColor; border-radius: 3px; width: 16px; height: 2px; top: -4px; left: -5px; }
effect
- Add the crossbeam portion of the trash can (usually representing the lid of the trash can).
Attribute explanationbackground: currentColor;
:
Use the current text color as the background color.
border-radius: 3px;
:
Add rounded corners to smoother the edges of the lid.
width: 16px; height: 2px;
:
Defines the size of the beam.
top: -4px; left: -5px;
:
Use absolute positioning to place the beam at the top of the trash can.
.gg-trash::before { width: 10px; height: 4px; border: 2px solid; border-bottom: transparent; border-top-left-radius: 2px; border-top-right-radius: 2px; top: -7px; left: -2px; }
effect
- Add the lid section of the trash can (curved top structure).
Attribute explanation
width: 10px; height: 4px;:
- Defines the width and height of the cover.
border: 2px solid;:
Set the border of the cover.
border-bottom: transparent;:
Remove the border at the bottom of the cover so that its opening faces downward.
border-top-left-radius and border-top-right-radius:
Set the two corners on the top of the cover to rounded corners.
top: -7px; left: -2px;:
Use absolute positioning to place the lid on top of the trash can.
Summary: The overall implementation of trash can icon
- .gg-trash is the main body of the trash can, including borders, shadows and other infrastructures.
- ::after Add crossbeam (lower part of trash can lid).
- ::before Add a curved structure on the top of the lid.
Combining these styles, a complete trash can icon is achieved.
Summary of interaction effects
- .delete-btn is hidden by default and is displayed when the user's mouse over .title.
- When the mouse is hovered, the trash can icon becomes a clickable state, providing visual prompts through the style cursor: pointer.
6. Find the current note id
const [currentNoteId, setCurrentNoteId] = ( (notes[0]?.id) || "" ) const currentNote = (note => === currentNoteId) || notes[0]
:
Define a state variablecurrentNoteId
and its corresponding update functionsetCurrentNoteId
。
notes[0]?.id
:
- Try to access the array with optional chain operator (?.).
notes
id of the first item. - If the notes array is empty or
notes[0]
forundefined
,notes[0]?.id
returnundefined
There will be no errors.
|| ""
:
ifnotes[0]?.id
forundefined
,currentNoteId
The initial value is set to an empty string""
。
Effect
If the notes array is not empty,currentNoteId
The initial value of the first note is the id. If the notes array is empty,currentNoteId
The initial value of ''.
(note => === currentNoteId)
:
- use
()
Methods look for id in notes arraycurrentNoteId
notes. -
find
The method returns the first element that satisfies the condition. If no matching element is found, returnundefined
。
|| notes[0]
:
If no matching notes were found (i.e.find
returnundefined
),use||
Provide default value, returnnotes[0]
(first item of the array).
This is the article about React self-study: How to use localStorage and how to delete notes. For more related React localStorage to delete notes, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!