1

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
  • 1
    I think you want to filter then map. e.g lessons.filter(lesson=>searchinput.toLowerCase().includes(lesson.title.toLowerCase())).map(props=><LessonCard {...props}/>) Commented Dec 4, 2022 at 19:57
  • 1
    It probably would be more readable to just create a state variable, like filteredLessons and doing your filtering either in your onChangeText callback or in a useEffect where searchinput is the dependency Commented Dec 4, 2022 at 20:01

2 Answers 2

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>
Sign up to request clarification or add additional context in comments.

Comments

1

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'
  },
});

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.