I have an array of Notes that I get from my database, the notes objects each have a category assigned to it. There are also buttons that allow the user to filter the notes by category and only render the ones with the corresponding one.
Now, it's all working pretty well but there's one annoying thing that I can't get rid of: whenever I click on any of the buttons: <button onClick={() => {handleClick(categoryItem.category)}}>{categoryItem.category}</button>, the filterNotes() function is only called on the second click. I suspect it has to do something with me calling setState() twice, or maybe with the boolean that I set in the functions, but I tried various combinations to call the function on the first click, but to no avail so far.
Here's my MainArea code:
import React, { useState, useEffect } from "react"; import Header from "./Header"; import Footer from "./Footer"; import ListCategories from "./ListCategories"; import Note from "./Note"; import axios from "axios" function CreateArea(props) { const [isExpanded, setExpanded] = useState(false); const [categories, setCategories] = useState([]) const [notes, setNotes] = useState([]) const [fetchB, setFetch] = useState(true) const [filterOn, setFilter] = useState(false) const [note, setNote] = useState({ title: "", content: "", category: '' }); useEffect(() => { fetch('http://localhost:5000/categories') .then(res => res.json()) .then(json => setCategories(json)) }, []) 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; console.log("handleChange called") 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){ if(filterOn){ fetch('http://localhost:5000/notes') .then(res => res.json()) .then(json => { console.log("filter notes") setNotes(json) setNotes(prevNotes => { console.log("setNotes called with category " + category) return prevNotes.filter((noteItem) => { return noteItem.category === category; }); }); setFilter(false) }) } } return ( <div> <Header/> <ListCategories categories={categories} notes={notes} filterNotes={filterNotes} setFilter={setFilter} filterOn={filterOn} setFetch={setFetch}/> <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> <Note notes={notes} setFetch={setFetch}/> <Footer/> <button onClick={()=>{setFetch(true)}}>All</button> </div> ); } export default CreateArea; And ListCategories where I get call the function and get the chosen category from the buttons:
import React, { useState } from "react"; import CreateCategory from "./CreateCategory"; export default function ListCategories(props) { function handleClick(category){ props.setFilter(true) props.filterNotes(category) } return ( <div className="category-group"> <CreateCategory/> <div className="btn-group"> {props.categories.map((categoryItem, index) =>{ return( <button onClick={() => {handleClick(categoryItem.category)}}>{categoryItem.category}</button> ) })} </div> </div> ) } I'm not sure what the best practice is with such behaviour - do I get the notes from the database each time as I'm doing now or should I do something completely different to avoid the double-click function call?
Thanks in advance for any suggestions!
<button onClick={() => {handleClick(categoryItem.category)}}>{categoryItem.category}</button>