mokiliii Lo
mokiliii Lo

Reputation: 635

ReactJS - Search/Iterate through array of objects

I have an object like that:

{
  "data": [
    {
      "id": "1234",
      "is_deleted": false,
      "name": "Sarah"
    },
    {
      "id": "3520",
      "is_deleted": true,
      "name": "Bobby"
    },
    {
      "id": "3520",
      "is_deleted": true,
      "name": "Sartah"
    }
  ]
}

React code

import React from 'react';
import { Input } from 'antd';
import { connect } from 'dva';

const Search = Input.Search;

@connect(({ rule, loading }) => ({
  rule,
  loading: loading.models.rule,
}))

export default class SearchBox extends React.Component {
    constructor(props) {
        super(props)
        this.state = {
            isListLoaded: false,
            resultArr: {}
        }
    }

    performSearch(value) {
    for( var i = this.props.rule.data.list.length; i--; ) {
        for (var key in this.props.rule.data.list[i]) {
            this.setState({resultArr: this.state.resultArr.push(i)});
            }
    }
    }

    componentDidMount() {
        if (!this.state.isListLoaded) {
            const { dispatch } = this.props;
            dispatch({
                type: 'rule/fetch'
            });
            this.setState({ isListLoaded: true });
    }
  }

  render() {
    return (
      <div>
           <Search
            placeholder="Search..."
                    onChange={(event) => this.performSearch(event.target.value)}
            style={{ width: "250px", "margin-left": "20px"}}
          />
      </div>
    );
  }
}

My goal is very simple: I want to search through this object, and return the entire array(s) that contains the keyword.

Example: if I search "Sar", I should get 2 objects:

{
  "id": "1234",
  "is_deleted": false,
  "name": "Sarah"
},
{
  "id": "3520",
  "is_deleted": true,
  "name": "Sartah"
}

Problem is, I get an error when I'm trying this code. I did search for previous solutions to this problem here on SO, but I can only find examples where there's only one element returned. What I want, is to get ALL the results that contain the keyword in ANY attributes (in this example, I'm returning 2 elements, not just one)

Any idea?

Upvotes: 4

Views: 17770

Answers (3)

radzak
radzak

Reputation: 3128

const { data } = {
  "data": [
    {
      "id": "1234",
      "is_deleted": false,
      "name": "Sarah"
    },
    {
      "id": "3520",
      "is_deleted": true,
      "name": "Bobby"
    },
    {
      "id": "3520",
      "is_deleted": true,
      "name": "Sartah"
    }
  ]
};

const keyword = "Sar";

const filtered = data.filter(entry => Object.values(entry).some(val => typeof val === "string" && val.includes(keyword)));

console.log(filtered);

It filters the entries of data Array with the following criterium: at least one of the entry's values must contain a given keyword.

Since IE doesn't yet support Object.values() and String.prototype.includes() you can use the following:

const containsKeyword = val => typeof val === "string" && val.indexOf(keyword) !== -1;

const filtered = data.filter(entry => Object.keys(entry).map(key => entry[key]).some(containsKeyword));

or polyfill these ES6 features, see more here.

To make the keyword lookup case insensitive, you can use RegExp:

const re = new RegExp(keyword, 'i');
const filtered = data.filter(entry => Object.values(entry).some(val => typeof val === "string" && val.match(re)));

Upvotes: 12

Rajendra Prasad
Rajendra Prasad

Reputation: 1

performSearch(value) {
    let filteredData = this.props.rule.data.list.filter(item => {
        let isFiltered = false;
        for(let key in item){
            if(item[key].includes(value)){
                isFiltered = true;
            }
        }
        return isFiltered;
    })
    this.setState({resultArr: filteredData});
}

Upvotes: 0

Muneeb
Muneeb

Reputation: 1559

Instead of looping through array simply use filter method of javascript

   performSearch(value) {
   const unfilteredData = this.props.rule.data.list;
   const filteredDate = unfilteredData.filter((val) => {
     return val.name.indexOf(val) !== -1;
   });
   this.setState({
      resultArr: filteredDate,
    })
  }

Upvotes: 0

Related Questions