I'm working on a note taking app. I would like to show the error message only if there is no search result. The problem is that currently I'm displaying the error message even when I don't have any notes in the array, which is not what I want. What am I doing wrong?
Here's my code and what I've tried so far:
const [notesList, setNotesList] = React.useState<string[]>([]);
const [query, setQuery] = React.useState<string>("");
const addNote = (): void => {
setNotesList([...notesList, ""]);
};
const deleteNote = React.useCallback(
(idx: number): void => {
const newList = [...notesList];
newList.splice(idx, 1);
setNotesList(newList);
},
[notesList]
);
const updateNote = React.useCallback(
(idx: number, text: string): void => {
const newList = [...notesList];
newList.splice(idx, 1, text);
setNotesList(newList);
},
[notesList]
);
React.useEffect(() => {
const storage_string = sessionStorage.getItem(LOCAL_STORAGE_KEY);
if (!storage_string) return;
try {
const savedNotes = JSON.parse(storage_string) as string[];
if (savedNotes) setNotesList(savedNotes);
} catch (err) {
console.log("error");
}
}, []);
React.useEffect(() => {
sessionStorage.setItem(LOCAL_STORAGE_KEY, JSON.stringify(notesList));
}, [notesList]);
const getFilteredNotes = (notes: string[], query: string) => {
if (!query) {
return notes;
}
return notes.filter((note) => note.includes(query));
};
const filteredNotes = getFilteredNotes(notesList, query);
const updateQuery = (event: React.ChangeEvent<HTMLInputElement>) =>
setQuery(event.target.value);
const handleSearch = debounce(updateQuery, 500);
return (
<div ref={wrapperRef}>
<GlobalStyle />
<SidePanel showSidePanel={showSidePanel}>
<HeaderContainer>
<SearchInput placeholder='Search notes' type='text' onChange={handleSearch} />
<Button variant='icon' onClick={addNote}>
<AddIcon/>
</Button>
</HeaderContainer>
{filteredNotes && filteredNotes.length > 0 ? filteredNotes.map((note: string, idx: number) => (
<Note
onChange={updateNote}
remove={deleteNote}
idx={idx}
text={note}
key={idx}
/>
)) : <Text>No results found</Text>}
</SidePanel>
<ToggleButton variant='primary' onClick={toggleSidePanel}>
<NoteIcon width='2rem' height='2rem'/>
Notes
</ToggleButton>
</div>
);
};
CodePudding user response:
Your condition will only ever render notes, or your fallback text:
{filteredNotes && filteredNotes.length > 0 ? filteredNotes.map((note: string, idx: number) => (
<Note
onChange={updateNote}
remove={deleteNote}
idx={idx}
text={note}
key={idx}
/>
)) : <Text>No results found</Text>}
As @kelly mentioned above, you need to check your notesList and if you don't want to show your fallback text then skip rendering this section.
There's many ways you can do that - abstracting the logic for what to render given different scenarios to a function would be more readable, but you can try this to see if it solves your problem:
{notesList.length > 0 && // <- this is new, and the rest is wrapped in parenthesis ()
(filteredNotes && filteredNotes.length > 0 ? (
filteredNotes.map((note: string, idx: number) => (
<Note
onChange={updateNote}
remove={deleteNote}
idx={idx}
text={note}
key={idx}
/>
))
) : (
<Text>No results found</Text>
))}
If your notesList is empty, it won't render anything