I am using hooks in my React application to handle state.
My application has notes
that are associated to categories by categoryId
.
Notes in a specific category are shown by mounting a NoteList
component.
<NoteList categoryObj={categoryObj} />
The NoteList
functional component
export const NoteList = (props) => {
const [notesToRender, setNotesToRender] = useState(props.notes)
useEffect(() => {
console.log('I fired!', props.categoryObj.id, props.notes)
setNotesToRender(props.notes)
}, [props.categoryObj.id]);
//...
return (
notesToRender.map((note) => {
return <NoteListItem key={note.id} {...note}/>
}
)
}
const mapStateToProps = (state) => {
notes: getNotesForCategory(state) // Selector that returns notes where note.id === props.categoryObj.id
}
export default connect(mapStateToProps)(NoteList)
Selector
export const getNotesForCategory = createSelector(
[getNotes, getcategoryId],
(notes, categoryId) => {
const categoryNotes = notes.filter(note => note.id === categoryId)
console.log('categoryNotes ', categoryNotes) // This log shows the correct notes
return categoryNotes
}
)
I create notesToRender
since I sometimes need to filter the notes before rendering them (that code is not shown here).
When switching between categories (props.categoryObj.id
updates) the notes does not show correctly.
When loading the app the state is correct, but when switching between categories the useEffect somehow causes the state to be "one step behind".
- Category A - Inital load - OK
- Switch to "Category B" - console.log() shows the correct categoryId, but notes from Category A
- Switch to "Category A" - console.log() shows the correct categoryId, but notes from Category B
- Switch to "Category B" - console.log() shows the correct categoryId, but notes from Category A
... and so on
The console log from the selector shows the correct notes.
The problem might be that mapStateToProps
triggers after the useEffect?
How can I make sure mapStateToProps
triggers before the useEffect without causing unnecessary re-renders === only when props.categoryObj.id
changes?
Kind regards /K
For me, the solution seems to be to change the useEffect() dependency from
props.categoryObj.id
toprops.notes
. My only hurdle now is how to compare two arrays of objects in the useEffect() dependency.Things I have tested so far are:
I have posted a new question here --> React useEffect() : Most efficient way to compare if two arrays of objects are equal