0

I'm trying to apply a filter in one array of objects with the property Id to get the list of items that starts with the text from an input. I have only two elements in the array but if I ever get the same two elements (render as a list).

What i need to do for fix the filter logic in function SearchFilter?

import React, { useEffect, useState } from "react"
import {useSelector} from 'react-redux'
import {View, Item, Text, Icon, Input, List, ListItem, Left, Thumbnail, Spinner} from 'native-base'

const SearchModal =(props:any)=>{
  const sessionsCata = useSelector((state)=> state.sessionsCata.sessions)
  const [itemsFiltered, setItemsFiltered] = useState([]) 
  const [showSpinner, setShowSpinner] =useState(false)

  //filter the array objects
  async function SearchFilter(params:string) {
    setShowSpinner(true)
    if(sessionsCata && sessionsCata.length>0){
        let result = await sessionsCata.filter(async x=> x.Id.startsWith(params) )
        if(result)
            setItemsFiltered(result)
    }            
    await Sleep(500) //function with Promise-setTimeout
    setShowSpinner(false)
  }

  return(
        <View style={StylesSearch.containerBar} >
            <Item rounded style={StylesSearch.searchBar}>
                <Input placeholder='Id...' onChangeText={async (text) => await SearchFilter(text)} />
            </Item>
        </View>
        <View> 
            { showSpinner ? <Spinner color='grey'/> :
                itemsFiltered && itemsFiltered.length>0 ? (
                    <List>
                    {
                        itemsFiltered.map(item=>(
                            <ListItem avatar key={item.id}>
                                <Body>
                                    <Text>{item.id}</Text>
                                </Body>
                            </ListItem>
                        ))
                    }                      
                    </List> 
                ): <Text>Not items filtered...</Text>
            }                                   
            </View>
   )
}
2
  • I don't understand what do you mean by this I have only two elements in the array but ever I get the same two elements (render as a list). Do you mean that you never get those two elements? Commented Nov 26, 2021 at 22:06
  • When i put any value in the input, ever render all the ítems Commented Nov 26, 2021 at 23:21

3 Answers 3

1

You don't need to use async/await on the filter. It's not async. Also, since itemsFiltered is deterministic (based on sessionsCata state), it shouldn't be its own state.

const [prefix, setPrefix] = useState("");

const itemsFiltered = sessionsCata.filter(x => x.Id.startsWith(prefix));

// Then
<Input onChangeText={setPrefix} />
Sign up to request clarification or add additional context in comments.

6 Comments

The itemsFiltered are not assignables, only use setItemsFiltered
Yes, remove const [itemsFiltered, setItemsFiltered] = useState([]) and use const itemsFiltered instead. That's what I mean by it shouldn't be its own state. It's deterministic. kentcdodds.com/blog/dont-sync-state-derive-it
error undefined is not an object (evaluating 'x.Id.startsWith')
undefined because the "useSelector((state)=> state.sessionsCata.sessions)" doesn't fill the variable before the definition of itemsFiltered
There should be some initial state in the redux so that this doesn't happen. You can also write (sessionsCata || []).filter(x => x?.Id?.startsWith(prefix)) which will never throw a type error.
|
0

Change :

if(sessionsCata && sessionsCata.length>0){
    let result = await sessionsCata.filter(async x=> x.Id.startsWith(params) )
    if(result)
    {
      if(JSON.stringify(itemsFiltered).includes(JSON.stringify(result)))
      return;
      setItemsFiltered(result)
    }        
} 

1 Comment

Not works, render crash
0

Finally i get it. The error was the property Id -> id.

And i quit async from the filter, put validation in params.

async function SearchFilter(params:string) {
    setShowSpinner(true)
    await Sleep(500)
    setShowSpinner(false)

    if(sessionsCata && sessionsCata.length>0 && params.length>0){
        let result = sessionsCata.filter( x=> x.id.startsWith(params) )
        if(result)
            setItemsFiltered(result)
    }            
}

Change input:

<Input placeholder='Id...' onChangeText={ (text) =>  SearchFilter(text)} />

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.