I write a React.js note web application where a user can add up to 10 notes.
I use map()
to iterate the array of notes, and a useState(1)
hook to update its count (the default number of notes is 1), so I would like to do something like this:
{[...Array(noteCount)].map((_, i) => <Note onUpdateNoteCount={() =>setNoteCount(n => n - 1)} key={i} />)}
The thing is that the Note() component is inside a Main() component which is in the App() component, so I want to get the needed values as props of App(), and than use them in Note(), but can not figure out how and where to put it.
Thanks!
App.js
import React from 'react';
import Header from './Header';
import Main from './Main';
function App () {
const [noteCount, setNoteCount] = React.useState(1);
function multiplyNoteComponent () {
if (noteCount < 20) {
setNoteCount(n => n + 1)
}
else {
alert('too many notes. remove or combine some of them together!')
}
}
return (
<div>
<Header/>
{[...Array(noteCount)].map((_, i) => <Main onUpdateNoteCount={() =>setNoteCount(n => n - 1)} key={i} />)}
<button
style={{left: '5%'}}
id='addNoteBtn'
onClick={multiplyNoteComponent}
title='Add a note'
>
+
</button>
</div>
);
}
export default App;
Main.js
import React from 'react';
import Note from './Note';
function Main () {
return (
<main>
your notes are:
<Note/>
</main>
)
}
export default Main;
Note.js
import React from 'react';
function Note () {
return (
<div> <button title='delete note' onClick={}>X</delete>
<li>
<input type='text'/>
</li>
</div>
)
}
export default Note
Edit: the reason I think I need the setNoteCount() function to be used in the Note() component, is for the count down when a note is being deleted (every note has its own delete button).
I would recommend this architecture of the your App.
Notes
array at the App
level.NoteInput
which adds a notes to your Notes
array.Notes
using the Note
component which takes onDelete
as a prop from App
level.App
component should be responsible for storing and delete a note from the state.In your example, notesCount
is meant to a derivative state.
i.e it could be derived simply from the Notes
array (notes.length).
So, rather than storing notesCount
, I recommend storing notes and deriving count from it.
You could see the working example here :- https://stackblitz.com/edit/react-g19tei
import React from "react";
import "./style.css";
const NOTES_ALLOWED = 10;
export default function App() {
const [notes, setNotes] = React.useState([]);
function addNote(newNote) {
if (notes.length === NOTES_ALLOWED) {
alert(`Only ${NOTES_ALLOWED} notes are allowed to be added`)
} else {
setNotes([...notes, newNote]);
}
}
function handleDelete(deleteNoteIdx) {
const newNotes = [...notes];
// delete the note at the specific index
newNotes.splice(deleteNoteIdx, 1)
setNotes(newNotes);
}
return (
<div>
<div style={{ marginTop: 20, marginBottom: 20 }}>
<p>Your notes are</p>
{notes.map((note, idx) => (
<Note
note={note}
onDelete={() => handleDelete(idx)}
/>
))}
</div>
<NoteInput onAdd={addNote} />
</div>
);
}
function Note({ note, onDelete }) {
return (
<div>
<p>{note}
<button onClick={onDelete}>Delete Note</button>
</p>
</div>
)
}
function NoteInput({ onAdd }) {
const [note, setNote] = React.useState('');
function handleSubmit(e) {
e.preventDefault();
const noteToBeSend = note;
setNote('')
onAdd(noteToBeSend.trim());
}
return (
<div>
<form onSubmit={handleSubmit}>
<input
type="text"
value={note}
onChange={e => setNote(e.target.value)}
required
/>
<button type="submit">Add Note</button>
</form>
</div>
)
}