Reputation: 107
I have a list of data here:
const Information = [
{
"id": 1,
"name":"Samule",
"age":25,
"keywords": ["USA","England"]
},
{
"id": 2,
"name":"Sam",
"age":19,
"keywords": ["Ghana"]
},
{
"id": 3,
"name":"Mark",
"age":17,
"keywords": ["Africa","England"]
},
{
"id": 4,
"name":"Markus",
"age":21,
"keywords": ["Africa","England"]
},
{
"id": 5,
"name":"Markus",
"age":29,
"keywords": ["Africa","Nigeria"]
}
];
export default Information;
And the reactjs code is here:
import React, { useState, useEffect } from "react";
import Information from './info-json'
export default function App() {
const [searchTerm, setSearchTerm] = useState("Ghana");
const [searchResults, setSearchResults] = useState([]);
const [searchTermTwo, setSearchTermTwo] = useState("Ghana");
const [searchResultsTwo, setSearchResultsTwo] = useState([]);
const handleChange = e => setSearchTerm(e.target.value);
const handleChangeTwo = e => setSearchTermTwo(e.target.value);
useEffect(() => {
const results = Information.filter(data => data.keywords.includes(searchTerm));
setSearchResults(results);
}, [searchTerm]);
useEffect(() => {
const resultsTwo = Information.filter(data => data.name.includes(searchTermTwo));
setSearchResultsTwo(results);
}, [searchTermTwo]);
return (
<div className="App">
<input
type="text"
value={searchTerm}
onChange={handleChange}
placeholder="search"
/>
<p>Search by Keyword</p>
<p>
searchTerm:
<br />
{searchTerm}
</p>
<input
type="text"
value={searchTermTwo}
onChange={handleChangeTwo}
placeholder="search"
/>
<p>Search by Name</p>
<p>
search name:
<br />
{searchTermTwo}
</p>
<div className="available-data">
<h1>Available Data</h1>
<p>"id": 1,
"name":"Samule",
"age":25,
"keywords": ["USA","England"]</p>
<p>
"id": 2,
"name":"Sam",
"age":19,
"keywords": ["Ghana"]
</p>
<p>
"id": 3,
"name":"Mark",
"age":17,
"keywords": ["Africa","England"]
</p>
<p>
"id": 4,
"name":"Markus",
"age":21,
"keywords": ["Africa","England"]
</p>
<p>
"id": 5,
"name":"Markus",
"age":29,
"keywords": ["Africa","Nigeria"]
</p>
</div>
<div className="results">
<h1>Results</h1>
<ul>
{searchResults &&
searchResultsTwo.map(item => <ul key={item.id} style={{border: "2px solid black", margin: "5px"}}>
<li>{item.name}</li>
<li>{item.age}</li>
</ul>)}
</ul>
</div>
</div>
);
}
What I want to do is to filter multiple values - a use case would be if I just type in Markus to the name field then ID 4 & 5 would show, but if I type in Markus in the first field and Nigeris into the second then only ID 5 would show.
I would then also like to filter by age.
Thanks in advance.
Upvotes: 2
Views: 104
Reputation: 15530
I would recommend to store filter object (properties and corresponding inputs) in your state, than (on render) check up against each object whether its respective properties contain desired inputs (or input is empty).
Following is a quick live demo that might give you a clue on how to approach your problem. I wouldn't recommend to deploy that as-is in your production app, though.
const { useState } = React,
{ render } = ReactDOM,
rootNode = document.getElementById('root')
const data = [{"id":1,"name":"Samule","age":25,"keywords":["USA","England"]},{"id":2,"name":"Sam","age":19,"keywords":["Ghana"]},{"id":3,"name":"Mark","age":17,"keywords":["Africa","England"]},{"id":4,"name":"Markus","age":21,"keywords":["Africa","England"]},{"id":5,"name":"Markus","age":29,"keywords":["Africa","Nigeria"]}]
const App = () => {
const [filterObj, setFilterObj] = useState({name:'', age:'', keywords:''}),
onFilter = ({target:{name, value}}) =>
setFilterObj({...filterObj, [name]: value})
return (
<div>
<label>Name</label>
<input name="name" value={filterObj.name} onChange={onFilter} />
<label>Keywords</label>
<input name="keywords" value={filterObj.keywords} onChange={onFilter} />
<label>Age</label>
<input type="number" name="age" value={filterObj.age} onChange={onFilter} />
<ul>
{
data.map(({id, name, age, keywords}) => {
const match = (name.toLowerCase().includes(filterObj.name.toLowerCase()) || !filterObj.name) &&
(`${age}`.includes(filterObj.age) || !filterObj.age) &&
(keywords.some(w => w.toLowerCase().includes(filterObj.keywords.toLowerCase())) || !filterObj.keywords)
return match && <li key={id}>{name}, {age} ({keywords.join(', ')})</li>
})
}
</ul>
</div>
)
}
render (
<App />,
rootNode
)
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.12.0/umd/react.production.min.js"></script><script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.11.0/umd/react-dom.production.min.js"></script><div id="root"></div>
Upvotes: 2