Dante Cervantes
Dante Cervantes

Reputation: 313

how to return all store when filter in react js and redux

i have an issue trying to create a "typehead" funcitonality in my app, i have an "input" that listen to onChange, and that onChange is calling to a Redux reducer that search for a tag in hole store, i need to retrive all matches with my search, over here everything is ok, but when i delete my search, my hole store is equals to my filtered results, and i want that when my search is empty it returns hole my store. (gif and code)

enter image description here

case 'SEARCH_BY_TAG':
            let tag = action.tag
            let filtered = state.slice(0)
            if(tag != ""){

                const copied = state.filter(item => {
                        return item.tags.find(obj => {
                            if(obj.name.indexOf(tag) > -1){
                                return true
                            }
                        })
                })

                return filtered = copied.filter(Boolean)

            }else{
                return filtered
            }

 break; 

Upvotes: 0

Views: 648

Answers (2)

Devin Howard
Devin Howard

Reputation: 705

I think you should refactor your state to change it from this:

[ item1, item2, item3, ... ]

to this:

{
  query: '',
  options: [ item1, item2, item3, ... ]
}

This way you can do what @Raspo said in his answer - do the filtering of the options in your render function.

Currently when you change the text in the search field, you are dispatching this action:

{ type: 'SEARCH_BY_TAG', tag: 'new query' }

I think you should change the action name, and the reducer code, to look more like this:

// note this is almost exactly the same as the old action
{
  type: 'CHANGE_AUTOCOMPLETE_QUERY',
  query: 'new query'
}

and the reducer could then change to this:

case CHANGE_AUTOCOMPLETE_QUERY:
  return Object.assign({}, state, {
    query: action.query
  })

Note that in the reducer case I just wrote, the options part of the state isn't changed at all. It remains constant.

Now let's assume your current render function looks something like this:

const options = reduxState // not sure exactly how you get the state but whatever
return (
  <div>
    {options.map(option => {
      <Option option={option} />
    })}
  </div>
)

This code relies on getting the state as an array. You could change it in the new setup to do this:

const query = reduxState.query
const options = reduxState.options.filter(item => {
  return item.tags.find(obj => {
    if(obj.name.indexOf(query) > -1){
      return true
    }
  })
})
return (
  <div>
    {options.map(option => {
      <Option option={option} />
    })}
  </div>
)

Upvotes: 1

Raspo
Raspo

Reputation: 1077

Instead of filtering things out inside your reducer, do it directly on render(), there is nothing wrong with that.

You can still use the SEARCH_BY_TAG action to keep track of the search keyword and use it to apply the filter when rendering your list.

Upvotes: 2

Related Questions