I'm using Zustand to store state, everything is working fine apart from this. When i click on the Song Buttons i want that to filter from the list.
Currently on fresh load it displays 3 songs. When clicking the button it should filter (and it does for first instance) but as soon as i click another button to filter again then nothing happens.
So if i chose / click Song 1
and Song 2
it should only show these songs.
I think the logic i wrote for that is correct but i must be doing something wrong with re-rendering.
Sorry i know people like to upload example here but i always find it hard with React files, so for this case I'm using https://codesandbox.io/s/damp-waterfall-e63mn?file=/src/App.js
Full code:
import { useEffect, useState } from 'react'
import create from 'zustand'
import { albums } from './albums'
export default function Home() {
const {
getFetchedData,
setFetchedData,
getAttrData,
setAttrData,
getAlbumData,
getButtonFilter,
setButtonFilter,
setAlbumData,
testState,
} = stateFetchData()
useEffect(() => {
if (getFetchedData) setAttrData(getFetchedData.feed.entry)
}, [getFetchedData, setAttrData])
useEffect(() => {
setAlbumData(getButtonFilter)
}, [getButtonFilter, setAlbumData])
// useEffect(() => {
// console.log('testState', testState)
// console.log('getAlbumData', getAlbumData)
// }, [getAlbumData, testState])
useEffect(() => {
setFetchedData()
}, [setFetchedData])
return (
<div>
<div>Filter to Show: {JSON.stringify(getButtonFilter)}</div>
<div>
{getAttrData.map((props, idx) => {
return (
<FilterButton
key={idx}
attr={props}
getDataProp={getButtonFilter}
setDataProp={setButtonFilter}
/>
)
})}
</div>
<div>
{getAlbumData?.feed?.entry?.map((props, idx) => {
return (
<div key={idx}>
<h1>{props.title.label}</h1>
</div>
)
})}
</div>
</div>
)
}
const FilterButton = ({ attr, getDataProp, setDataProp }) => {
const [filter, setFilter] = useState(false)
const filterAlbums = async (e) => {
const currentTarget = e.currentTarget.innerHTML
setFilter(!filter)
if (!filter) setDataProp([...getDataProp, currentTarget])
else setDataProp(getDataProp.filter((str) => str !== currentTarget))
}
return <button onClick={filterAlbums}>{attr.album}</button>
}
const stateFetchData = create((set) => ({
getFetchedData: albums,
setFetchedData: async () => {
set((state) => ({ ...state, getAlbumData: state.getFetchedData }))
},
getAttrData: [],
setAttrData: (data) => {
const tempArr = []
for (const iterator of data) {
tempArr.push({ album: iterator.category.attributes.label, status: false })
}
set((state) => ({ ...state, getAttrData: tempArr }))
},
getButtonFilter: [],
setButtonFilter: (data) => set((state) => ({ ...state, getButtonFilter: data })),
testState: {
feed: { entry: [] },
},
getAlbumData: [],
setAlbumData: (data) => {
set((state) => {
console.log(' ~ file: index.js ~ line 107 ~ state', state)
const filter = state.getAlbumData.feed?.entry.filter((item) =>
data.includes(item.category.attributes.label),
)
return {
...state,
getAlbumData: {
...state.getAlbumData,
feed: {
...state.getAlbumData.feed,
entry: filter,
},
},
}
})
},
}))
Sample data:
export const albums = {
feed: {
entry: [
{ title: { label: 'Song 1' }, category: { attributes: { label: 'Song 1' } } },
{ title: { label: 'Song 2' }, category: { attributes: { label: 'Song 2' } } },
{ title: { label: 'Song 3' }, category: { attributes: { label: 'Song 3' } } },
],
},
}