react on change check if equal to array of object - javascript

i have input and array of object
i need when i type it will display the object. "airplaneCompany" is the object property that i need to compare
i was doing only if the input is equal to the "airplaneCompany" it will return it by the filter method
but i need for evrey char it will check it and if the object start with "a" it will show this object
const [txtInp, setTxtInp] = useState("");
const showFlight = users.filter((user) => {
return user.airplaneCompany == txtInp;
});
{showFlight.map((user, index) => {
const { id, airplaneCompany, passenger } = user;
return (
<div className="flightContainer" key={index}>
<div>{id}</div>
<div>{airplaneCompany}</div>
<div>{passenger}</div>
</div>
);
})}

You can use #Patrick answer, but JavaScript has its own startsWith function you can use.
Also, consider wrapping the filter with the useMemo hook to run it only when the input changes and not on every render.
const showFlight = useMemo(() => {
return users.filter((user) => {
return user.airplaneCompany == txtInp;
});
}, [txtInp]);

I think you can use your .filter function to check if the airplaneCompany starts with the user input?
Something like
return user.airplaneCompany.indexOf(txtInp) === 0;

just use regex. just place input value like /^airplaneCompany$/
const wrongInputText = 'q'
const rightInputText = 'airplaneCompany'
console.log('wrong', 'return value=', /^airplaneCompany$/.test(wrongInputText))
console.log('right', 'return value=',/^airplaneCompany$/.test(rightInputText))

Related

Remove element from useState array by index

SOLUTION: Update the key value for the input element to refresh the default value => content of the input element. Deleting an element from the array DID work. Thanks for your help!
src: https://thewebdev.info/2022/05/12/how-to-fix-react-input-defaultvalue-doesnt-update-with-state-with-javascript/#:~:text=state%20with%20JavaScript%3F-,To%20fix%20React%20input%20defaultValue%20doesn't%20update%20with%20state,default%20value%20of%20the%20input.
I got an useState array in my code which represents a lisst of students:
const [students, setStudents] = useState([""]);
This array gets mapped to student elements:
{students.map((student, index) => <Student setStudents={setStudents} students={students} id={index} key={index} content={student} />)} I also got an AddStudent element which adds students to the array.
function AddStudent(props) {
const {setStudents} = props;
return (
<button className="change-student add-student" onClick={() => {
setStudents((students) => [...students, ""])
}}>
+
</button>
);
}
The RemoveStudent component is supposed to remove a student by its index in the array. I've tried many different ways but none worked correctly. How can I get it to work? Here is my code:
function RemoveStudent(props) {
const {students, setStudents, id} = props;
return (
<button className="change-student remove-student" onClick={() => {
let data = students;
if(id > -1) {
data.splice(id, 1);
}
console.log(data)
// setStudents(data)
// alternative:
// setStudents(students.filter(index => index !== id)); // removes the last element in the list
// doesn't work properly
}}>
-
</button>
)
}
Thanks for your help!
2 things should be noted here:
While updating react state arrays, use methods that return a new array (map, filter, slice, concat),
rather than ones that modify the existing array (splice, push, pop, sort).
While updating React state using its previous value, the callback argument should be used for the state setter. Otherwise you may get stale values. (See React docs).
if(id > -1) {
setStudents(students=> students.filter((s,i)=>(i != id)))
}
Consult this article, for a complete reference about how to update React state arrays.
You need to copy the students array first and then try removing the student by index. I assume by id you mean index at which to remove the student. Then you can try something like:
function RemoveStudent(props) {
const {students, setStudents, id} = props;
return (
<button
className="change-student remove-student"
onClick={() => {
if(id > -1) {
const data = [...students]; // making a copy
data.splice(id, 1); // removing at index id
console.log(data)
setStudents(data)
}
}}
>
-
</button>
)
}
With array.filter() you have a mistake in how you pass callback to filter() method. Please try the following:
setStudents(students.filter((,index) => index !== id));
Notice the index is second param of the callback so I used a , before index.
After #Irfanullah Jan 's answer you should make sure how you show the student.
Here is the simple example:
const [students, setStudents] = useState([1, 2, 3]);
return (
<div>
{students.map((student, index) => {
return <div>{student}</div>; // show the value not the index
})}
<button
onClick={() => {
let id = 1;
const copy = [...students];
copy.splice(id, 1)
console.log(copy)
setStudents(copy);
}}
>
-
</button>
</div>
);
The code above will delete the student of "index==1"

Return multiple elements from a function number property

Is there a way i can return multiple elements from a function based off a number property that it ingests? For example: I have an element of a coin, which is just a <div className="coin"></div>" and I'd like to have a function where I can say {displayCoins(5)}, and the param it takes is the number of coins to return.
What I've tried so far is the following
const displayCoins = (numberOfCoins) => {
let elCoin = document.createElement('div')
elCoin.className = "coin"
return elCoin * numberOfCoins
}
Thank you
If you want to return multiple elements you can return an array of them. You don't need to create DOM elements manually with document.createElement('div'), you can simply create them, or template them specifically, in JSX.
const displayCoins = (numberOfCoins) => {
return [...Array(numberOfCoins).keys()].map(el => (
<div key={el} className="coin">
));
}

How I can manage the state for 4 Checkbox in functional component in ReactJS?

How I would create a functional component with exactly 4 checkboxes? I have created dynamically mapping an array and I set its value with:
const [checked, setChecked] = useState([false, false, false, false])
and then, with a function I change its state, something like:
const checkboxes = array.map( (el, index) => {
return <Checkbox
checked={checked[index]}
onChange={checkedHandler}/>
}
This is the handler:
const checkedHandler = (event, index) => {
setChecked(...)
//Well, here I don't know how change the particular value of the array...
}
Or I must create a useState for each Checkbox checked state? And how pass the state of this Checkbox to the father component if it was necessary?
You are invoking the checkedHandler wrong way. You have:
onChange={checkedHandler}
And you should have:
onChange={() => {checkedHandler(index)}}
In the handler itself you should copy your current array to prevent its mutation and change the value of the indexed one:
const checkedHandler = (index) => {
const newChecked = [...checked];
newChecked[index] = !checked[index]; // toogle the checkbox
setChecked(newChecked);
}
Assign id to each checkbox like id="1", id="2" and so on...
Then your checkedHandler() function be like:
checkedHandler(event) {
const newChecked = [...checked]
newChecked[parseint(event.target.id) - 1] = true
setChecked(newChecked)
}
There is ALOT of ways you can do this, if you case is simple, you could just shallow copy the array and change only the index you want.
let newChecked = [...checked]
newChecked[index] = value
setChecked(newChecked)
But for more complex cases, please take a look at Correct modification of state arrays in ReactJS

Filter table data

I want to filter a table based on few conditions .. Below is the sample image
code I've tried
this.reportData.filter(it => {
if (
it.startTimeFilter.includes(this.startdatefilter) &&
it.endTimeFilter.includes(this.enddatefilter) &&
it.status.toLowerCase().includes(this.status)
) {
this.filteredData.push(it);
}
});
Ok, I can give you some hint to achieve this as I do not have full code. Make sure this.reportData is never changed as we need all data to have filtering
applyFiltering(){
this.dataToShowOnUI = getFilteredData();
}
getFilteredData(): any[]{
let filteredData = JSON.parse(JSON.stringify(this.reportData));
if(this.startdatefilter && this.enddatefilter){
filteredData = filteredData.filter(it =>
it.startTimeFilter.includes(this.startdatefilter) &&
it.endTimeFilter.includes(this.enddatefilter)
);
}
if(this.status){
filteredData = filteredData.filter(data => data.status.toLowerCase().includes(this.status))
}
if(this.operatingSystem){
filteredData = filteredData.filter(data => data.operatingSystem.toLowerCase().includes(this.operatingSystem))
}
// and so on ...
return filteredData;
}
I'm assuming that this.reportData and this.filteredData are arrays. Then the correct way of using filter method is the following:
this.filteredData = this.reportData.filter(it =>
it.startTimeFilter.includes(this.startdatefilter) &&
it.endTimeFilter.includes(this.enddatefilter) &&
it.status.toLowerCase().includes(this.status)
);
Basically, the parameter of filter should be a function that returns boolean value (which tells if the element should be kept as result), and it returns the filtered new array without modifying the given one.

Trouble with React/JS filter

I am trying to implement a filter function that is able to search in two separate JSON fields when a user types in a search bar. Searching the whole JSON returns errors and if I repeat this function, the two similar functions cancel each other out.
My current filter function:
let filteredOArt = origArt.filter((origAItem) => {
return origAItem.authors.toLowerCase().includes(this.state.search.toLowerCase())
});
I want to be able to have the search look within the "authors" field as well as a "description" field.
Before the React render, I have this function listening to the state:
updateSearch(event) {
this.setState({ search: event.target.value })
}
Then my search function is in an input field in the React return:
<h6>Search by author name: <input type="text" value={this.state.search} onChange={this.updateSearch.bind(this)} /></h6>
You can tweak the function a bit like this
let filteredOArt = origArt.filter((origAItem) => {
return (
(origAItem.authors.toLowerCase().includes(this.state.search.toLowerCase())||
(origAItem.description.toLowerCase().includes(this.state.search.toLowerCase())
)
)
});
You actually can do a filter for both fields.
Given you have your searchValue and your array with the objects you could filter this way:
const filterByAuthorOrDescription = (searchValue, array) =>
array.filter(
item =>
item.authors.toLowerCase().includes(searchValue.toLowerCase()) ||
item.description.toLowerCase().includes(searchValue.toLowerCase())
);
const filtered = filterByAuthorOrDescription(this.state.search, articles);
filtered will now contain an array of objects that contain your searchValue in either description or authors that you can map through.
You could use some to check if the filter is positive for at least one field :
let filteredOArt = origArt.filter(origAItem => ['authors', 'description'].some(field => origAItem.[field].toLowerCase().includes(this.state.search.toLowerCase())))
Just iterate over the different field names you want to use.
Some will return true if any of the fields mentioned contains your string and avoid repetitions in your code.
Long syntax :
origArt.filter(origAItem => {
return ['authors', 'description'].some(field => origAItem.[field].toLowerCase().includes(this.state.search.toLowerCase()))
})

Categories

Resources