skip to Main Content

My current issue is filtering through a array of "lessons" with a search input. When a user first goes to the lessons components all the lessons are loaded if the search input text is nothing. When i type something though(if if it matches it) it will not show up and everything will just not show.

my code:(lessonCard is the component of each lesson)**took away the database query because it was too long

export default function Learn() {
  const [lessons,setLessons] = useState([])
  const [searchinput,setSearchInput] = useState("")      
  return (
    <View style={learnStyle.maincont}>
      <View style={learnStyle.learncont}>
      <Text style={learnStyle.even}>EVVENNTI</Text>
      <Text style={learnStyle.learn}>Learn</Text>
      </View>
      <View style={{marginTop:20,flexDirection:"row", width:"100%",alignItems:"center",backgroundColor:"#F3F5F9",borderRadius:20,paddingLeft:15}}>
      <Feather name="search" size={24} color="#FF802C"style={{flex:0.1}} />
        <TextInput style={{padding:20,borderRadius:20,flex:0.9}} placeholder="type lesson keyword" placeholderTextColor="grey" color="#000"  value={searchinput} onChangeText={(val) => setSearchInput(val)}/>
      </View>
{li ?       <View style={{width:"100%",flexDirection:"row",marginTop:30,borderRadius:20,backgroundColor:"#CFECFE"}}>
      <View style={{flex:0.5,padding:20}}>
        <Text style={{fontSize:20,fontWeight:"700",marginBottom:20}}>What do you want to learn Today?</Text>
        <View style={{backgroundColor:"#FF7F2D",padding:8,borderRadius:20}}>
          <Button title='Get Started' color="#fff"/>
        </View>
      </View>
      <View style={{flex:0.5,marginLeft:10}}>
        <Image source={{uri:"https://cdn.discordapp.com/attachments/783336191529320498/1048439876741251072/Screen_Shot_2022-12-02_at_10.25.38_PM.png"}}  style={{width:"100%",height:200,borderRadius:20}}/>
      </View>
     </View> : null}
          <View>
          <Text style={{fontSize:28,marginTop:20}}>Courses</Text>
         <ScrollView style={{paddingBottom:200}}>
          {searchinput === "" ?  lessons.map((doc,key) => 
          <>
      <LessonCard key={key} setModalVisible={setModalVisible} title={doc.title} desc={doc.desc} img1={doc.imgURL} modalVisible={modalVisible} />
          </>): lessons.filter((lessons) => {
            if(searchinput.toLocaleLowerCase().includes(lessons.title)) {
              <LessonCard key={key} setModalVisible={setModalVisible} title={doc.title} desc={doc.desc} img1={doc.imgURL} modalVisible={modalVisible} />
            } else {null}
          })}
         <View style={{height:600,width:"100%"}}></View>
         </ScrollView>
          </View>
    </View>
  )
}

so basically im trying to see weather or not my search input includes the lesson title and if it does to show it like in this code below

  {searchinput === "" ?  lessons.map((doc,key) => 
          <>
      <LessonCard key={key} setModalVisible={setModalVisible} title={doc.title} desc={doc.desc} img1={doc.imgURL} modalVisible={modalVisible} />
          </>): lessons.filter((lessons) => {
            if(searchinput.toLocaleLowerCase().includes(lessons.title)) {
              <LessonCard key={key} setModalVisible={setModalVisible} title={doc.title} desc={doc.desc} img1={doc.imgURL} modalVisible={modalVisible} />
            } else {null}
          })}

what would be the correct javascript/react syntax to fully show the lessons that match the search input?

2

Answers


  1. .filter returns an array based on the condition (which is .includes in your case). So you should write your filter logic and then calling .map on the filtered array to return your components.

    <div>
      <InfoBlock data={DATASET} />
      <InfoBlock data={RAW_MEDIA} />
    {
      searchinput === "" ?  
        lessons.map((lesson, key) => 
          <LessonCard key={key} setModalVisible={setModalVisible} title={lesson.title} desc={lesson.desc} img1={lesson.imgURL} modalVisible={modalVisible} />
        )
      : 
        lessons.filter((lesson) => searchinput.toLocaleLowerCase().includes(lesson.title) ? 1 : -1).map((lesson) => {
          if(searchinput.toLocaleLowerCase().includes(lesson.title)) {
            return <LessonCard key={key} setModalVisible={setModalVisible} title={lesson.title} desc={lesson.desc} img1={lesson.imgURL} modalVisible={modalVisible} />;
          } else {
            return null;
          }
        })
    }
    </div>
    
    Login or Signup to reply.
  2. Expanding on my comment (demo):

    import React, { useEffect, useState } from 'react';
    import { Text, View, StyleSheet, ScrollView,Image } from 'react-native';
    import Constants from 'expo-constants';
    import { TextInput } from 'react-native-paper';
    
    export default function App() {
      const [lessons, setLessons] = useState([]);
      const [filteredLessons, setFilteredLessons] = useState([]);
      const [searchinput, setSearchInput] = useState('');
    
      useEffect(() => {
        // fetch data on mount
        const getData = async () => {
          const results = await fetch('https://dummyjson.com/products');
          const json = await results.json();
          setLessons(json.products);
          console.log(json.products[0])
        };
        getData();
      }, []);
      useEffect(() => {
        // when lessons or searchinput changes update filteredLessons
        const newLessons = lessons.filter((lesson) =>
          lesson.title.toLowerCase().includes(searchinput.toLowerCase())
        );
        setFilteredLessons(searchinput.length < 1 ? lessons : newLessons);
      }, [lessons, searchinput]);
      return (
        <View style={styles.container}>
          <TextInput
            value={searchinput}
            onChangeText={setSearchInput}
            label="Search"
            dense
            mode="outlined"
          />
          <View style={{ flex: 1 }}>
            <ScrollView
              style={{ flex: 1 }}
              
            >
              {filteredLessons.map((item,i)=>{
                return (
                  <View style={styles.item}>
                    <Text>{item.title}</Text>
                    <Image
                      source={{uri:item.images[0]}}
                      style={styles.image}
                    />
                  </View>
                );
              })}
            </ScrollView>
          </View>
        </View>
      );
    }
    
    const styles = StyleSheet.create({
      container: {
        flex: 1,
        justifyContent: 'center',
        paddingTop: Constants.statusBarHeight,
        backgroundColor: '#ecf0f1',
        padding: 8,
      },
      image:{
        width:150,
        height:100
      },
      item: {
        padding: 5,
        margin: 5,
        justifyContent:'center',
        alignItems:'center'
      },
    });
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search