0

I'm new to react and want to make search filter for multiple data in the object. I've tried for filtering single data, code is as shown below:

    var {Data, search} =this.state;
            search = this.state.search.trim().toLowerCase();
        if (search.length > 0) {
          Data= Data.filter(function(i) {
            return i.firstName.toLowerCase().match( search );

          });
        }

It is working great but only for the firstName. But my objective is to get filter for lastName, Location and Skills also.

Here is the code:

export default class DataView extends React.Component {
  constructor() {
    super();
    this.state = {
      Data: [],
      search: ""
    };
  }
  componentDidMount() {
    this.fetchData();
  }
  fetchData() {
    fetch("api/Profile")
      .then(response => response.json())
      .then(data => {
        this.setState({
          Data: data.item1
        });
      });
  }
  handleSearch = e => {
    this.setState({ search: e.target.value });
  };

  render() {
    var { Data, search } = this.state;
    search = this.state.search.trim().toLowerCase();
    if (search.length > 0) {
      Data = Data.filter(function(i) {
        return i.firstName.toLowerCase().match(search);
      });
    }

    return (
      <div>
        <Segment className="p_segment">
          <Input
            icon="search"
            placeholder="Search..."
            className="a_Search"
            value={this.state.search}
            onChange={this.handleSearch}
          />
        </Segment>

        <Container className="p_view">
          {Data.map(View => {
            return (
              <Grid key={View.id}>
                <Grid.Row className=" p_header">
                  <Checkbox className="p_checkbox" />
                  <Header>
                    {" "}
                    {View.firstName} {View.lastName}{" "}
                  </Header>
                </Grid.Row>
                <Divider className="p_divider" />
                <Grid.Row>
                  <Icon name="marker" /> {View.location}
                  <Divider className="p_divider" />
                </Grid.Row>
                <Grid.Row>
                  <Grid.Column>
                    <div>
                      <div className="g_column">
                        {View.skillset.map(data => {
                          return (
                            <Label className="c_label">{data.skill}</Label>
                          );
                        })}
                      </div>
                    </div>
                  </Grid.Column>
                </Grid.Row>
              </Grid>
            );
          })}
        </Container>
      </div>
    );
  }
}

Can anyone help me in this Query?

3
  • Is skillset an array and you would like to search in this array too? Commented Mar 25, 2020 at 9:02
  • 1
    Could you please create working sample?? Commented Mar 25, 2020 at 9:04
  • @Agney - Yes Correct. Commented Mar 25, 2020 at 9:04

3 Answers 3

2

You can simply make an OR statement

return i.firstName.toLowerCase().match( search ) || i.skills.toLowerCase().match( search ) || i.location.toLowerCase().match( search );

Or if you want to search the full object

return JSON.stringify(i).toLowerCase().match(search);
Sign up to request clarification or add additional context in comments.

1 Comment

@Sandhya : accepting above answer is an extremely poor choice - first suggested solution will turn into the dumb lump of OR chained conditions if you need to check 5, 10, 15 props; second option is outright wrong - it will match not only property values but property names just as well, so, whenever you search for some string that partially matches your key name, you'll get the entire array instead of proper match. I don't even speak performance (but even for 3 records above solution may result into 20% performance loss, imagine 100 records, 1000...
1

If case-insensitive partial match across the object values is what you've been after, you may simply extract Object.values() into an array and make use of Array.prototype.some() together with Array.prototype.filter() in a similar way to what you did:

const stateData = [{
          firstName: 'Stephen',
          lastName: 'Smith',
          location: 'Johannesburg',   //match by location
          skills: 'golf'
        },{
          firstName: 'George',
          lastName: 'Washington',
          location: 'Philadelphia',
          skills: 'majohng'           //match by skills
        },{
          firstName: 'Dummy',
          lastName: 'Dummyson',
          location: 'Dummywille',
          skills: 'dummy'
      }],
      searchString = 'jo',
      
      searchResult = stateData.filter(record => 
        Object
          .values(record)
          .some(prop => 
            prop
              .toLowerCase()
              .includes(searchString.toLowerCase())
           )
       )
        
console.log(searchResult)
.as-console-wrapper{min-height:100%;}

Comments

0

Some notation.

var { Data, search } = this.state; // don't use var
    search = this.state.search.trim().toLowerCase(); // don't do mutation
    if (search.length > 0) {
      Data = Data.filter(function(i) { // don't do mutation
        return i.firstName.toLowerCase().match(search);
      });
    }
  1. Add result to state.
  2. use componentDidUpdate.
  3. check if the search filed was changed.
  4. do filter.
  5. reset result if the search field empty.

import React from "react";

export default class DataView extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      data: [],
      search: "",
      result: [], // [1]
    };
  }

  componentDidMount() {
    this.fetchData();
  }
  
  componentDidUpdate(prevProps, prevState) { // [2]
    const { search: prevSearch } = prevState;
    const { search: nextSearch, data } = this.state;
    
    if (prevSearch !== nextSearch) { // [3]
      const trimed = nextSearch.trim().toLowerCase();
      const result = nextSearch.length > 0
      ? data.filter(({ firstName, lastName }) => ( // [4]
        `${firstName} ${lastName}`.toLowerCase().includes(trimed)
      ))
      : []; // [5]
      
      this.setState({ result });
    }
  }

  fetchData() {
    fetch("api/Profile")
      .then(response => response.json())
      .then(({ item1 }) => {
        this.setState({ data: item1 });
      });
  }
  handleSearch = (e) => {
    this.setState({ search: e.target.value });
  };

  render() {
    const { data, search, result } = this.state;

    return (
      <div>
        <Segment className="p_segment">
          <Input
            icon="search"
            placeholder="Search..."
            className="a_Search"
            value={search}
            onChange={this.handleSearch}
          />
        </Segment>

        <Container className="p_view">
          {result.map((view) => {
            const {
              id,
              firstName,
              lastName,
              location,
              skillset,
            } = view;
            
            return (
              <Grid key={id}>
                <Grid.Row className=" p_header">
                  <Checkbox className="p_checkbox" />
                  <Header>
                    {` ${firstName} ${lastName} `}
                  </Header>
                </Grid.Row>
                <Divider className="p_divider" />
                <Grid.Row>
                  <Icon name="marker" /> {location}
                  <Divider className="p_divider" />
                </Grid.Row>
                <Grid.Row>
                  <Grid.Column>
                    <div>
                      <div className="g_column">
                        {skillset.map(({ skill }) => (
                          <Label className="c_label">{skill}</Label>
                        ))}
                      </div>
                    </div>
                  </Grid.Column>
                </Grid.Row>
              </Grid>
            );
          })}
        </Container>
      </div>
    );
  }
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

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.