I have a sample list of which is an array of objects with three fields in the App component. The list is passed as a prop to an "booksearch" component which handles the logic to search and filter the list based on search text. below is the JSX which renders the book. I am doubting issue is with the "matcheBook" method.
<div className="output-container">
{this.props.books
.filter((e) => this.matchesBook(e))
.map((b) => (
<div className="output-card" key={b.title}>
{Object.entries(b).map(([k, v]) => (
<div key={v} className="out-section">
<span className="heading">
<b>{k}</b>
</span>
<span className="details">{v}</span>
</div>
))}
</div>
))}
</div>
method for handling the search text
handleChange(evt, name) {
let searchText = evt.target.value;
this.setState((state) => ({
...state,
fields: {
...state.fields,
[name]: searchText
}
}));
}
filtering logic
matchesBook(book) {
const { fields } = this.state;
return Object.entries(book).some(
([k, v]) =>
!fields[k] ||
v.toString()
.toLowerCase()
.includes(fields[k].toString().trim().toLowerCase())
);
}
State shape
this.state = {
fields: initialFields
};
"initialFields" comes from below
const fieldsArray = ["author", "title", "year"];
const initialFields = fieldsArray.reduce(
(a, e) => ({
...a,
[e]: ""
}),
{}
);
CodePudding user response:
I've never tried some() function, but doing the search function code on my own way I modified your matchesBook function into this one:
matchesBook(book) {
const { fields } = this.state;
let matching = 0;
for (let i = 0; i < Object.entries(fields).length; i ) {
if (Object.entries(fields)[i][1] === "") {
matching ;
} else {
if(String(Object.entries(book)[i][1]).toLowerCase().includes(String(Object.entries(fields)[i][1]).toLowerCase())){
matching ;
}
}
}
return matching === Object.entries(fields).length;
}
Try it, it'll work!
CodePudding user response:
According to MDN some()
method executes the callbackFn
function once for each element present in the array until it finds the one where callbackFn
returns a truthy value (a value that becomes true when converted to a Boolean). If such an element is found, some()
immediately returns true.
In your case !fields[k]
always return true when its value is ""
and so it never have to compare succeeding values in the array which contains the field we are checking, in this case year
. Please see example below.
const book = {
author: "Charles Dickens",
title: "The Pickwick Papers",
year: "1837"
};
const fields = {author: "", title: "", year: "lookinforthisstringinbook"};
const checkValue = Object.entries(book).some(
([k, v]) =>
!fields[k] || // --> always returns true
v.toString()
.toLowerCase()
.includes(fields[k].toString().trim().toLowerCase())
);
console.log(checkValue)