Related
The story is, I should be able to put Bob, Sally and Jack into a box. I can also remove either from the box. When removed, no slot is left.
people = ["Bob", "Sally", "Jack"]
I now need to remove, say, "Bob". The new array would be:
["Sally", "Jack"]
Here is my react component:
...
getInitialState: function() {
return{
people: [],
}
},
selectPeople(e){
this.setState({people: this.state.people.concat([e.target.value])})
},
removePeople(e){
var array = this.state.people;
var index = array.indexOf(e.target.value); // Let's say it's Bob.
delete array[index];
},
...
Here I show you a minimal code as there is more to it (onClick etc). The key part is to delete, remove, destroy "Bob" from the array but removePeople() is not working when called. Any ideas? I was looking at this but I might be doing something wrong since I'm using React.
When using React, you should never mutate the state directly. If an object (or Array, which is an object too) is changed, you should create a new copy.
Others have suggested using Array.prototype.splice(), but that method mutates the Array, so it's better not to use splice() with React.
Easiest to use Array.prototype.filter() to create a new array:
removePeople(e) {
this.setState({people: this.state.people.filter(function(person) {
return person !== e.target.value
})});
}
To remove an element from an array, just do:
array.splice(index, 1);
In your case:
removePeople(e) {
var array = [...this.state.people]; // make a separate copy of the array
var index = array.indexOf(e.target.value)
if (index !== -1) {
array.splice(index, 1);
this.setState({people: array});
}
},
Here is a minor variation on Aleksandr Petrov's response using ES6
removePeople(e) {
let filteredArray = this.state.people.filter(item => item !== e.target.value)
this.setState({people: filteredArray});
}
Simple solution using slice without mutating the state
const [items, setItems] = useState(data);
const removeItem = (index) => {
setItems([
...items.slice(0, index),
...items.slice(index + 1)
]);
}
Use .splice to remove item from array. Using delete, indexes of the array will not be altered but the value of specific index will be undefined
The splice() method changes the content of an array by removing existing elements and/or adding new elements.
Syntax: array.splice(start, deleteCount[, item1[, item2[, ...]]])
var people = ["Bob", "Sally", "Jack"]
var toRemove = 'Bob';
var index = people.indexOf(toRemove);
if (index > -1) { //Make sure item is present in the array, without if condition, -n indexes will be considered from the end of the array.
people.splice(index, 1);
}
console.log(people);
Edit:
As pointed out by justin-grant, As a rule of thumb, Never mutate this.state directly, as calling setState() afterward may replace the mutation you made. Treat this.state as if it were immutable.
The alternative is, create copies of the objects in this.state and manipulate the copies, assigning them back using setState(). Array#map, Array#filter etc. could be used.
this.setState({people: this.state.people.filter(item => item !== e.target.value);});
Easy Way To Delete Item From state array in react:
when any data delete from database and update list without API calling that time you pass deleted id to this function and this function remove deleted recored from list
export default class PostList extends Component {
this.state = {
postList: [
{
id: 1,
name: 'All Items',
}, {
id: 2,
name: 'In Stock Items',
}
],
}
remove_post_on_list = (deletePostId) => {
this.setState({
postList: this.state.postList.filter(item => item.post_id != deletePostId)
})
}
}
filter method is the best way to modify the array without touching the state.
It returns a new array based on the condition.
In your case filter check the condition person.id !== id and create a new array excluding the item based on condition.
const [people, setPeople] = useState(data);
const handleRemove = (id) => {
const newPeople = people.filter((person) => person.id !== id);
setPeople( newPeople);
};
<button onClick={() => handleRemove(id)}>Remove</button>
Not advisable:
But you can also use an item index for the condition if you don't have any id.
index !== itemIndex
This is your current state variable:
const [animals, setAnimals] = useState(["dogs", "cats", ...])
Call this function and pass the item you would like to remove.
removeItem("dogs")
const removeItem = (item) => {
setAnimals((prevState) =>
prevState.filter((prevItem) => prevItem !== item)
);
};
your state variable now becomes:
["cats", ...]
Another way of doing it is by using useState hook. Check docs: https://reactjs.org/docs/hooks-reference.html#functional-updates It states: Unlike the setState method found in class components, useState does not automatically merge update objects. You can replicate this behavior by combining the function updater form with object spread syntax as shown below or use useReducer hook.
const [state, setState] = useState({});
setState(prevState => {
return {...prevState, ...updatedValues};
});
Some answers mentioned using 'splice', which did as Chance Smith said mutated the array. I would suggest you to use the Method call 'slice'
(Document for 'slice' is here) which make a copy of the original array.
Just filter out deleted item and update the state with remaining items again,
let remainingItems = allItems.filter((item) => {return item.id !== item_id});
setItems(remainingItems);
const [people, setPeople] = useState(data);
const handleRemove = (id) => {
const newPeople = people.filter((person) => { person.id !== id;
setPeople( newPeople );
});
};
<button onClick={() => handleRemove(id)}>Remove</button>
It's Very Simple
First You Define a value
state = {
checked_Array: []
}
Now,
fun(index) {
var checked = this.state.checked_Array;
var values = checked.indexOf(index)
checked.splice(values, 1);
this.setState({checked_Array: checked});
console.log(this.state.checked_Array)
}
removePeople(e){
var array = this.state.people;
var index = array.indexOf(e.target.value); // Let's say it's Bob.
array.splice(index,1);
}
Redfer doc for more info
Almost all the answers here seem to be for class components, here's a code that worked for me in a functional component.
const [arr,setArr]=useState([]);
const removeElement=(id)=>{
var index = arr.indexOf(id)
if(index!==-1){
setArr(oldArray=>oldArray.splice(index, 1));
}
}
If you use:
const[myArr, setMyArr] = useState([]);
for add:
setMyArr([...myArr, value]);
and for remove:
let index = myArr.indexOf(value);
if(index !== -1)
setPatch([...myArr.slice(0, index), ...myArr.slice(index, myArr.length-1)]);
Removing an element with a certain value
//
Note filter function always returns a new array.
const people = ["Bob", "Sally", "Jack"]
const removeEntry = (remove) => {
const upDatePeople = people.filter((Person) =>{
return Person !== remove
});
console.log(upDatePeople)
//Output: [ 'Sally', 'Jack' ]
}
removeEntry("Bob");
You forgot to use setState. Example:
removePeople(e){
var array = this.state.people;
var index = array.indexOf(e.target.value); // Let's say it's Bob.
delete array[index];
this.setState({
people: array
})
},
But it's better to use filter because it does not mutate array.
Example:
removePeople(e){
var array = this.state.people.filter(function(item) {
return item !== e.target.value
});
this.setState({
people: array
})
},
const [randomNumbers, setRandomNumbers] = useState([111,432,321]);
const numberToBeDeleted = 432;
// Filter (preferred)
let newRandomNumbers = randomNumbers.filter(number => number !== numberToBeDeleted)
setRandomNumbers(newRandomNumbers);
//Splice (alternative)
let indexOfNumberToBeDeleted = randomNumbers.indexOf(numberToBeDeleted);
let newRandomNumbers = Array.from(randomNumbers);
newRandomNumbers.splice(indexOfNumberToBeDeleted, 1);
setRandomNumbers(newRandomNumbers);
//Slice (not preferred - code complexity)
let indexOfNumberToBeDeleted = randomNumbers.indexOf(numberToBeDeleted);
let deletedNumber = randomNumbers.slice(indexOfNumberToBeDeleted, indexOfNumberToBeDeleted+1);
let newRandomNumbers = [];
for(let number of randomNumbers) {
if(deletedNumber[0] !== number)
newRandomNumbers.push(number);
};
setRandomNumbers(newRandomNumbers);
The story is, I should be able to put Bob, Sally and Jack into a box. I can also remove either from the box. When removed, no slot is left.
people = ["Bob", "Sally", "Jack"]
I now need to remove, say, "Bob". The new array would be:
["Sally", "Jack"]
Here is my react component:
...
getInitialState: function() {
return{
people: [],
}
},
selectPeople(e){
this.setState({people: this.state.people.concat([e.target.value])})
},
removePeople(e){
var array = this.state.people;
var index = array.indexOf(e.target.value); // Let's say it's Bob.
delete array[index];
},
...
Here I show you a minimal code as there is more to it (onClick etc). The key part is to delete, remove, destroy "Bob" from the array but removePeople() is not working when called. Any ideas? I was looking at this but I might be doing something wrong since I'm using React.
When using React, you should never mutate the state directly. If an object (or Array, which is an object too) is changed, you should create a new copy.
Others have suggested using Array.prototype.splice(), but that method mutates the Array, so it's better not to use splice() with React.
Easiest to use Array.prototype.filter() to create a new array:
removePeople(e) {
this.setState({people: this.state.people.filter(function(person) {
return person !== e.target.value
})});
}
To remove an element from an array, just do:
array.splice(index, 1);
In your case:
removePeople(e) {
var array = [...this.state.people]; // make a separate copy of the array
var index = array.indexOf(e.target.value)
if (index !== -1) {
array.splice(index, 1);
this.setState({people: array});
}
},
Here is a minor variation on Aleksandr Petrov's response using ES6
removePeople(e) {
let filteredArray = this.state.people.filter(item => item !== e.target.value)
this.setState({people: filteredArray});
}
Simple solution using slice without mutating the state
const [items, setItems] = useState(data);
const removeItem = (index) => {
setItems([
...items.slice(0, index),
...items.slice(index + 1)
]);
}
Use .splice to remove item from array. Using delete, indexes of the array will not be altered but the value of specific index will be undefined
The splice() method changes the content of an array by removing existing elements and/or adding new elements.
Syntax: array.splice(start, deleteCount[, item1[, item2[, ...]]])
var people = ["Bob", "Sally", "Jack"]
var toRemove = 'Bob';
var index = people.indexOf(toRemove);
if (index > -1) { //Make sure item is present in the array, without if condition, -n indexes will be considered from the end of the array.
people.splice(index, 1);
}
console.log(people);
Edit:
As pointed out by justin-grant, As a rule of thumb, Never mutate this.state directly, as calling setState() afterward may replace the mutation you made. Treat this.state as if it were immutable.
The alternative is, create copies of the objects in this.state and manipulate the copies, assigning them back using setState(). Array#map, Array#filter etc. could be used.
this.setState({people: this.state.people.filter(item => item !== e.target.value);});
Easy Way To Delete Item From state array in react:
when any data delete from database and update list without API calling that time you pass deleted id to this function and this function remove deleted recored from list
export default class PostList extends Component {
this.state = {
postList: [
{
id: 1,
name: 'All Items',
}, {
id: 2,
name: 'In Stock Items',
}
],
}
remove_post_on_list = (deletePostId) => {
this.setState({
postList: this.state.postList.filter(item => item.post_id != deletePostId)
})
}
}
filter method is the best way to modify the array without touching the state.
It returns a new array based on the condition.
In your case filter check the condition person.id !== id and create a new array excluding the item based on condition.
const [people, setPeople] = useState(data);
const handleRemove = (id) => {
const newPeople = people.filter((person) => person.id !== id);
setPeople( newPeople);
};
<button onClick={() => handleRemove(id)}>Remove</button>
Not advisable:
But you can also use an item index for the condition if you don't have any id.
index !== itemIndex
This is your current state variable:
const [animals, setAnimals] = useState(["dogs", "cats", ...])
Call this function and pass the item you would like to remove.
removeItem("dogs")
const removeItem = (item) => {
setAnimals((prevState) =>
prevState.filter((prevItem) => prevItem !== item)
);
};
your state variable now becomes:
["cats", ...]
Another way of doing it is by using useState hook. Check docs: https://reactjs.org/docs/hooks-reference.html#functional-updates It states: Unlike the setState method found in class components, useState does not automatically merge update objects. You can replicate this behavior by combining the function updater form with object spread syntax as shown below or use useReducer hook.
const [state, setState] = useState({});
setState(prevState => {
return {...prevState, ...updatedValues};
});
Some answers mentioned using 'splice', which did as Chance Smith said mutated the array. I would suggest you to use the Method call 'slice'
(Document for 'slice' is here) which make a copy of the original array.
Just filter out deleted item and update the state with remaining items again,
let remainingItems = allItems.filter((item) => {return item.id !== item_id});
setItems(remainingItems);
const [people, setPeople] = useState(data);
const handleRemove = (id) => {
const newPeople = people.filter((person) => { person.id !== id;
setPeople( newPeople );
});
};
<button onClick={() => handleRemove(id)}>Remove</button>
It's Very Simple
First You Define a value
state = {
checked_Array: []
}
Now,
fun(index) {
var checked = this.state.checked_Array;
var values = checked.indexOf(index)
checked.splice(values, 1);
this.setState({checked_Array: checked});
console.log(this.state.checked_Array)
}
removePeople(e){
var array = this.state.people;
var index = array.indexOf(e.target.value); // Let's say it's Bob.
array.splice(index,1);
}
Redfer doc for more info
Almost all the answers here seem to be for class components, here's a code that worked for me in a functional component.
const [arr,setArr]=useState([]);
const removeElement=(id)=>{
var index = arr.indexOf(id)
if(index!==-1){
setArr(oldArray=>oldArray.splice(index, 1));
}
}
If you use:
const[myArr, setMyArr] = useState([]);
for add:
setMyArr([...myArr, value]);
and for remove:
let index = myArr.indexOf(value);
if(index !== -1)
setPatch([...myArr.slice(0, index), ...myArr.slice(index, myArr.length-1)]);
Removing an element with a certain value
//
Note filter function always returns a new array.
const people = ["Bob", "Sally", "Jack"]
const removeEntry = (remove) => {
const upDatePeople = people.filter((Person) =>{
return Person !== remove
});
console.log(upDatePeople)
//Output: [ 'Sally', 'Jack' ]
}
removeEntry("Bob");
You forgot to use setState. Example:
removePeople(e){
var array = this.state.people;
var index = array.indexOf(e.target.value); // Let's say it's Bob.
delete array[index];
this.setState({
people: array
})
},
But it's better to use filter because it does not mutate array.
Example:
removePeople(e){
var array = this.state.people.filter(function(item) {
return item !== e.target.value
});
this.setState({
people: array
})
},
const [randomNumbers, setRandomNumbers] = useState([111,432,321]);
const numberToBeDeleted = 432;
// Filter (preferred)
let newRandomNumbers = randomNumbers.filter(number => number !== numberToBeDeleted)
setRandomNumbers(newRandomNumbers);
//Splice (alternative)
let indexOfNumberToBeDeleted = randomNumbers.indexOf(numberToBeDeleted);
let newRandomNumbers = Array.from(randomNumbers);
newRandomNumbers.splice(indexOfNumberToBeDeleted, 1);
setRandomNumbers(newRandomNumbers);
//Slice (not preferred - code complexity)
let indexOfNumberToBeDeleted = randomNumbers.indexOf(numberToBeDeleted);
let deletedNumber = randomNumbers.slice(indexOfNumberToBeDeleted, indexOfNumberToBeDeleted+1);
let newRandomNumbers = [];
for(let number of randomNumbers) {
if(deletedNumber[0] !== number)
newRandomNumbers.push(number);
};
setRandomNumbers(newRandomNumbers);
I've an array of errors, each error has a non-unique param attribute.
I'd like to filter the array based on whether the param has been seen before.
Something like this:
const filteredErrors = [];
let params = [];
for(let x = 0; x < errors.length; x++) {
if(!params.includes(errors[x].param)) {
params.push(errors[x].param);
filteredErrors.push(errors[x]);
}
}
But I've no idea how to do this in ES6.
I can get the unique params const filteredParams = Array.from(new Set(errors.map(error => error.param)));
but not the objects themselves.
Pretty sure this is just a weakness in my understanding of higher order functions, but I just can't grasp it
You could destrucure param, check against params and add the value to params and return true for getting the object as filtering result.
As result you get an array of first found errors of the same type.
const
params = [],
filteredErrors = errors.filter(({ param }) =>
!params.includes(param) && params.push(param));
Instead of an array you can make use of an object to keep a map of existing values and make use of filter function
let params = {};
const filteredErrors = errors.filter(error => {
if(params[error.param]) return false;
params[error.param] = true;
return true;
});
i'd probably do it like this with a reduce and no need for outside parameters:
const filteredErrors = Object.values(
errors.reduce((acc, val) => {
if (!acc[val.param]) {
acc[val.param] = val;
}
return acc;
}, {}))
basically convert it into an object keyed by the param with the object as values, only setting the key if it hasn't been set before, then back into an array of the values.
generalized like so
function uniqueBy(array, prop) {
return Object.values(
array.reduce((acc, val) => {
if (!acc[val[prop]]) {
acc[val[prop]] = val;
}
return acc;
}, {}))
}
then just do:
const filteredErrors = uniqueBy(errors, 'param');
If your param has a flag identifier if this param has been seen before then you can simply do this.
const filteredErrors = errors.filter(({ param }) => param.seen === true);
OR
const filteredErrors = errors.filter((error) => error.param.seen);
errors should be an array of objects.
where param is one of the fields of the element of array errors and seen is one of the fields of param object.
You can do it by using Array.prototype.reduce. You need to iterate through the objects in the array and keep the found params in a Set if it is not already there.
The Set.prototype.has will let you find that out. If it is not present in the Set you add it both in the Set instance and the final accumulated array, so that in the next iteration if the param is present in your Set you don't include that object:
const errors = [{param: 1, val: "err1"}, {param: 2, val: "err2"}, {param: 3, val: "err3"}, {param: 2, val: "err4"}, {param: 1, val: "err5"}];
const { filteredParams } = errors.reduce((acc, e) => {
!acc.foundParams.has(e.param) && (acc.foundParams.add(e.param) &&
acc.filteredParams.push(e));
return acc;
}, {foundParams: new Set(), filteredParams: []});
console.log(filteredParams);
I try to replace map to reduce but without success. Can you help me rewrite this piese of code:
this.tares = this.tares
.map(tare => {
let suppliers = [];
this.organizations.forEach(organization => {
if (organization.tare_ids.indexOf(tare.id) !== -1) {
suppliers = suppliers.concat(tare.suppliers);
}
});
return { ...tare, suppliers };
});
My supplier variable as an accumulator parameter of a reduce function but in this case, I can't figure out how to apply reduce. Nested arrays crashing me.
You could take a Set for all id and map the array with an object and a check if id exists.
var ids = this.organizations.reduce(
(s, { tare_ids }) => tare_ids.reduce((t, id) => t.add(id), s),
new Set
);
this.tares = this.tares.map(tare => ({ ...tare, suppliers: ids.has(tare.id) ? tare.suppliers : [] }));
I have an object that contains an array called applicants:
const persons={"entities":{"applicants":[{"lastName":"Agamemnon","isPrimaryApplicant":false,"id":"16671520038"},{"lastName":"Purdy","isPrimaryApplicant":true,"id":"16671520039"},{"lastName":"Brekky","isPrimaryApplicant":true,"id":"16671520040"},{"lastName":"Abouli","isPrimaryApplicant":true,"id":"16671520041"}]}}
How can I return the item from the entities.applicants array by id?
I tried something like:
const applicantsById = persons.entities.applicants.find(a => a.id ===id)
console.log(applicantsById.get('16671520041'))
But I can't figure out how to pass in the id?
codepen
Using vanilla javascript:
You need to define what id is before you set your applicantsById variable. This way you can find an id in your array of objects which equals the id you defined.
const id = '16671520041';
const applicantsById = persons.entities.applicants.find(a => a.id === id);
You can extend this to a function if you wish to use this with multiple ids:
const persons = {"entities":{"applicants":[{"lastName":"Agamemnon","isPrimaryApplicant":false,"id":"16671520038"},{"lastName":"Purdy","isPrimaryApplicant":true,"id":"16671520039"},{"lastName":"Brekky","isPrimaryApplicant":true,"id":"16671520040"},{"lastName":"Abouli","isPrimaryApplicant":true,"id":"16671520041"}]}};
const getApplicantById = _id => persons.entities.applicants.find(({id}) => id === _id);
console.log(getApplicantById('16671520041')); // Abouli obj
console.log(getApplicantById('16671520039')); // Purdy obj
Or, using Lodash and ES6:
const persons = {"entities":{"applicants":[{"lastName":"Agamemnon","isPrimaryApplicant":false,"id":"16671520038"},{"lastName":"Purdy","isPrimaryApplicant":true,"id":"16671520039"},{"lastName":"Brekky","isPrimaryApplicant":true,"id":"16671520040"},{"lastName":"Abouli","isPrimaryApplicant":true,"id":"16671520041"}]}};
const id = "16671520041";
const res = _.find(persons.entities.applicants, {id});
console.log(res); // Abouli obj
<script src="https://cdn.jsdelivr.net/lodash/4.16.4/lodash.min.js"></script>
applicantsById needs to be a function parametrized on the id
const persons={"entities":{"applicants":[{"lastName":"Agamemnon","isPrimaryApplicant":false,"id":"16671520038"},{"lastName":"Purdy","isPrimaryApplicant":true,"id":"16671520039"},{"lastName":"Brekky","isPrimaryApplicant":true,"id":"16671520040"},{"lastName":"Abouli","isPrimaryApplicant":true,"id":"16671520041"}]}}
const applicantsById = id => persons.entities.applicants.find(a => a.id ===id)
console.log(applicantsById('16671520041'))
You should create a function.
const applicantsById = (id) => persons.entities.applicants.find(a => a.id === id)
applicantsById('16671520041')
this will return you required result
You can either define your id before you do your find:
const id = '16671520041';
const applicantsById = persons.entities.applicants.find(a => a.id ===id)
Or you can define a function that accepts an id as an argument. The other answers have covered how to do this with modern ES6 arrow functions. If you're unfamiliar with them here's the ES5 function declaration-way of writing it. Here I've also passed in the persons data to the function.
const persons={"entities":{"applicants":[{"lastName":"Agamemnon","isPrimaryApplicant":false,"id":"16671520038"},{"lastName":"Purdy","isPrimaryApplicant":true,"id":"16671520039"},{"lastName":"Brekky","isPrimaryApplicant":true,"id":"16671520040"},{"lastName":"Abouli","isPrimaryApplicant":true,"id":"16671520041"}]}}
// Accept persons data, and an id
function getApplicantById(persons, id) {
// Return the found applicant from the function
return persons.entities.applicants.find(a => a.id ===id);
}
// Pass in the data, and the id to the function
const applicant = getApplicantById(persons, '16671520041');
console.log(applicant);
Use filter for this
const persons={"entities":{"applicants":[{"lastName":"Agamemnon","isPrimaryApplicant":false,"id":"16671520038"},{"lastName":"Purdy","isPrimaryApplicant":true,"id":"16671520039"},{"lastName":"Brekky","isPrimaryApplicant":true,"id":"16671520040"},{"lastName":"Abouli","isPrimaryApplicant":true,"id":"16671520041"}]}}
console.log(get(16671520039));
function get(id)
{
return persons.entities.applicants.filter((e)=>e.id===id)
}