0

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' } } },
    ],
  },
}
Marius
  • 1,664
  • 2
  • 16
  • 28
  • Not to solve your problem, but if you have such nested data, consider using [Immer](https://immerjs.github.io/immer/). – rodrigocfd Jan 25 '22 at 18:59

0 Answers0