I have an app that allows user take and delete notes and I'm trying to implement the edit function. The problem is that I don't want to take the user to a different page, I was the note they click on to change into a form or some kind of editable space (prepopulated with the current content of the note) that they can then save so that it renders again but with the updated values (Google Keep style).
The things that I'm struggling with is how to change just one note since the notes are mapped to components through an array - I've tried using the filter()
method and playing with ternary operators, but I either copy the entire array or nothing happens. I came across this question: Google Keep edit functionality, but I'm struggling to understand what's happening and how to adapt it in my code.
So the main question is: how can I change one component without disrupting the other elements in the array or their positions on the page?
Here's my Note component so far:
import React, { useState, useEffect} from "react";
import axios from "axios";
function Note(props) {
const [noteToEdit, setNoteToEdit] = useState({
title: "",
content: "",
category: ''
})
const [isEditNote, setEditNote] = useState(false)
const [idToEdit, setIdToEdit] = useState('')
function deleteNote(id) {
axios.delete(`http://localhost:5000/notes/${id}`)
.then(() => { console.log("Note successfully deleted")
props.setFetch(true)
});
}
function editNote(id, title, content, category){
setEditNote(true)
setNoteToEdit(prevNote => {
return {
title : title,
content : content,
category : category
};
});
console.log("Current note to edit after useState:")
setIdToEdit(id)
console.log(noteToEdit)
}
return (
<div>
{isEditNote && <h1>want to edit: {idToEdit}</h1>}
{!isEditNote &&
<div>
{props.notes.map((noteItem) => {
return (
<div className="note">
<h1>{noteItem.title}</h1>
<p>{noteItem.content}</p>
<button onClick={() => {editNote(noteItem._id, noteItem.title, noteItem.category, noteItem.content)}}>
Edit
</button>
<button onClick={() => {deleteNote(noteItem._id)}}>
Delete
</button>
<p>{noteItem.category}</p>
</div>
);
})}
</div>
}
</div>
)
}
export default Note
and my CreateArea component:
import React, { useState, useEffect } from "react";
import Header from "./Header";
import Footer from "./Footer";
import ListCategories from "./ListCategories";
import CreateCategory from "./CreateCategory";
import Note from "./Note";
import axios from "axios"
import Container from 'react-bootstrap/Container';
import Row from 'react-bootstrap/Row';
import Col from 'react-bootstrap/Col';
function CreateArea() {
const [isExpanded, setExpanded] = useState(false);
const [categories, setCategories] = useState([])
const [notes, setNotes] = useState([])
const [fetchB, setFetch] = useState(true)
const [fetchCategories, setFetchCategories] = useState(true)
const [noteToEdit, setNoteToEdit] = useState({
title: "",
content: "",
category: ''
})
const [ieditNote, setEditNote] = useState(false)
const [note, setNote] = useState({
title: "",
content: "",
category: ''
});
useEffect(() => {
if(fetchCategories){
fetch('http://localhost:5000/categories')
.then(res => res.json())
.then(json => {
setCategories(json)
setFetchCategories(false)
})
}
}, [fetchCategories])
useEffect(() => {
if(fetchB) {
fetch('http://localhost:5000/notes')
.then(res => res.json())
.then(json => {
console.log(json)
setNotes(json)
setFetch(false)
})
}
}, [fetchB])
function handleChange(event) {
const { name, value } = event.target;
setNote(prevNote => {
return {
...prevNote,
[name]: value
};
});
}
function submitNote(e){
e.preventDefault();
axios.post("http://localhost:5000/notes/add-note", note)
.then((res) => {
setNote({
category: '',
title: "",
content: ""
})
setFetch(true)
console.log("Note added successfully");
console.log(note)
})
.catch((err) => {
console.log("Error couldn't create Note");
console.log(err.message);
});
}
function expand() {
setExpanded(true);
}
function filterNotes(category){
fetch('http://localhost:5000/notes')
.then(res => res.json())
.then(json => {
const filtered = json.filter((noteItem) => (noteItem.category === category));
setNotes(filtered);
})
}
function editNote(id, title, content, category){
setNoteToEdit(prevNote => {
return { ...prevNote };
});
console.log("Current note to edit after useState:")
console.log(noteToEdit)
}
return (
<div>
<Header/>
<div className="categories">
<CreateCategory setFetchCategories={setFetchCategories}/>
<button className="all-button" onClick={()=>{setFetch(true)}}>All</button>
<ListCategories categories={categories} notes={notes} filterNotes={filterNotes} setFetch={setFetch}/>
</div>
<div className="notes-container">
<form className="create-note">
{isExpanded && (
<input
name="title"
onChange={handleChange}
value={note.title}
placeholder="Title"
/>
)}
<textarea
name="content"
onClick={expand}
onChange={handleChange}
value={note.content}
placeholder="Take a note..."
rows={isExpanded ? 3 : 1}
/>
<select
name="category"
onChange={handleChange}
value={note.category}>
{
categories.map(function(cat) {
return <option
key={cat.category} value={cat.value} > {cat.category} </option>;
})
}
</select>
<button onClick={submitNote}>Add</button>
</form>
<div className="notes-group">
<Note notes={notes} setFetch={setFetch} editNote={editNote} setEditNote={setEditNote}/>
</div>
</div>
<Footer/>
</div>
);
}
export default CreateArea;
Would appreciate any guidance on this, thanks!