I have two array one is the state like this
const [state,setState] = useState([])
and the another one is am getting from a form when it is submitted;
ids = [4,5,6]
setState(ids)
Now, when i update the state second time the values are there i.e 4,5,6 in the state.
so the values are getting duplicated ie 4,5,6,4,5,6
What i want is to make sure that only the elements which is not present in the array gets pushed not all,and i get the valid output like following.
4,5,6,7
If 7 is added.
What i did is like this, which is totally wrong
const filterss = [...state];
setState([]);
filterss.push(values);
setState(filterss);
const ids=[4,5,6]
let formSubmitIds=[4,5,6,7]
let uniquieIds=[...new Set([...ids,...formSubmitIds])]
console.log(uniquieIds)
Simply use this logic to setState accordingly i.e setState(uniquieIds)
ids are the stored values in state
formSubmitIds is the new array which you are getting on submit of form
[...ids,...formSubmitIds] will merge both arrays
Set is used to remove duplicates
[......new Set] will convert Set back to an array with unique ids only
const filters = [...state];
values.forEach(item => {
if (filters.indexOf(item) < 0) {
filters.push(item);
}
})
setState(filters);
First push all the old and new values in a single array then try using Set() to get unique values in the array.
Here's the code.
setState(new Set(arrayName))
Use Set() constructor to achieve your goal.
Try:
const [state, setState] = useState([])
const ids = [4,5,6]
const formSubmittedIds = [4,5,6,7]
setState([...new Set([...ids, ...formSubmittedIds])]) // Sets [4, 5, 6, 7] to the state
Happy coding :)
Related
I am creating a filter for a diagram. Whenever a filter is clicked it should remove that category from the diagram. The api call returns an object with names. let’s say the object returns 40 items and I want to filter 5 out by name. What is the best way to approach this?.
I tried to manually type the property names into an array and run the .filter on my object like below. However it returns the entire object unfiltered.
filterDiagram() {
Const array = [“all the names of the properties I want to filter out”]
carbonates = array.forEach(x) => {console.log(x)}
Const filterCat = data.filter (io =>
io.name !== carbonates)
}
Let's say, the array consists of all the names/categories you want to take out.
const toBetakenOut = ['fruits','salts', 'etc' ]
// Please make sure they are not 1 string but rather comma-separated values.
You can filter the API data by using the filter function on the data,to remove objects with names that are within toBetakenOut.
const filterCat = data.filter (io => !toBetakenOut.includes(io.name))
function filterDiagram(){
const dontWantsArray = [/*all of the things you dont want*/];
// Outputs an array of keys
const filteredKeys = Object.keys(yourJSObject)
.filter(key => !dontWantsArray.includes(key));
// After you found the keys you can get the values to another array by keys
const filteredValues = filteredKeys.map(key => yourJSObject[key]);
}
Trying to find the flaw in my logic. I have a slice of state called companies that is initialized to an empty array:
const [companies, setCompanies] = useState([]);
I have my data coming in which is an array of objects with company data in it. I want to push the company names to the companies state but check if the name already exists there. This is the solution I came up with but for some reason I keep getting each item to show up in the state array even if it already exists.
// Data is an array of objects containing company data including the company name (companyName)
// State
const [companies, setCompanies] = useState([]);
useEffect(() => {
const companyNames = data.map(app => app.companyName);
const filteredName = companyNames.filter(name => companies.includes(name) === false);
setCompanies(filteredName);
}, [data])
// Expected Output ==> [array with no repeating names]
// Current OutPut ==> [all names even if they appear more than once]
The javascript set object is tailor-made for this.
see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set
// Use to remove duplicate elements from the array
const numbers = [2,3,4,4,2,3,3,4,4,5,5,6,6,7,5,32,3,4,5]
console.log([...new Set(numbers)])
// [2, 3, 4, 5, 6, 7, 32]
You could filter the array before you process it to get only unique values, like so:
[1,2,3,2,4,3,1].filter((el, index, arr) => arr.indexOf(el) === index) // yields [1,2,3,4]
or use a Javascript Set.
I am trying to dynamically add an object to an array of objects, I have been trying to Destructuring the main object but it adds a number to the end of the parent array. This is what I have:
const [data, setData] = useState ([
{
_id:1,
firstName:'Leo',
lastName:'Miller',
telephone:'+569273829',
mail:'leo.miller#gmail.com',
work:[
{_id:1, startWorkDate:'01/01/2015', endWorkDate:'01/02/2017', work:'description...'},
{_id:2, startWorkDate:'01/01/2018', endWorkDate:'01/02/2020', work:'description...'}
]
}];
I generate dynamically this object:
const value = {_id:3, startWorkDate:'01/01/2018', endWorkDate:'01/02/2020', work:'description...'}
I need to add it into data.work and after that update only the description of work._id[3]
I try with this function
const addNewWork = (value) => {
let copyData = [...data, data[0].workExperience.push(value)]
return setData(copyData)
}
but for some reason doesn't add correctly the object. Help please!
You have an array and not an object. Your statement
let copyData = [...data, data[0].workExperience.push(value)]
is doing two things:
mutating the state by doing push(). Which is not the react way.
creating a new array. Also adding a new item to the array, but that is the new length of data[0].workExperience.
The return value of Array.prototoype.push is:
The new length property of the object upon which the method was called.
What you have to do is:
Make a copy of the array. Can use ... (spread operator) here.
Make a copy of the array object you want (first index). Try to add the object to its specific property workExperience.
const addNewWork = (value) => {
let newData = [...data];
let newWorkExperienceArray =
[...data[0].workExperience,value];
let newDataFirstObject = {...data[0], workExperience : newWorkExperienceArray};
newData[0] = newDataFirstObject;
return setData(newData)
}
You can also update the property. I didn't find the relevant code in your question as to what I have to update so I didn't update anything in the third workExperience object.
EDIT: It seems in your code the property name is work and not workExperience. Please confirm. The above code uses workExperience, you can replace it by work if that is the case
You can do this with this simple function:
const addNewWork = (value) => {
let updatedObj = data[0];
updatedObj.work.push(value)
// updates your object each time
let copyData = [updatedObj]
// adds a new object for each call
// let copyData = [...data, updatedObj]
return setData(copyData)
}
Now it updates the object in your state. If you want to add a new object for each call just uncomment let copyData = [...data, updatedObj] and comment out let copyData = [updatedObj]
When you set state for array your setter is a quite bite different
setData(prevData => [...prevData, newItem]) // to add a single item to array
setData(prevData => newArray) // to replace entire array
I am trying to dynamically assign data to a variable based on object array values.
I am going to present a simplified data structure:
const data = [{"age":25,"name":"Michael"},{"age":20,"name":"Lara"}]
const data2 = [{"age":26,"name":"Sarah"},{"age":21,"name":"David"}]
I want to assign values to variables. For example, I know this works:
const arr = 'data'
const zero = '0'
const a = 'age'
const test = `${data[zero][a]}`
console.log(test) // returns 25
But can I assign it dynamically(maybe nested template literal)?
const test = `${arr[zero][a]}`
console.log(test) // does not work, because arr is a string
const test = `${${arr}[zero][a]}`
console.log(test) // does not work
Is there any way to achieve this?
Thank you in advance!
Edit:
I overthought the solution(tried to be fancy with template literals).
To solve it, thanks to the input from ggorlen I changed the way my data was stored. That way, it was way easier to access the data dynamically. The solution was fairly similar to the answer from Sowmen Rahman.
I was trying too hard to think about solving a problem in a specific way, when a different approach was more sensible!
Something like this won't be possible in the way you're suggesting. Strings can't be dynamically converted to variable names by itself, however if you stored your variables in a dictionary or map object, you can use the subscript operator [] to achieve the task.
const data = [{"age":25,"name":"Michael"},{"age":20,"name":"Lara"}]
const data2 = [{"age":26,"name":"Sarah"},{"age":21,"name":"David"}]
const rootObject = {
data: data,
data2: data2
}
const arr = 'data'
const zero = '0'
const a = 'age'
const test = `${rootObject[arr][zero][a]}`
console.log(test) // outputs 25
I added pagination to a project I'm working on, which uses React and Redux.
When I create a new item, I want it appended to the current list, while also removing the last item in the list; as each page has a limit to how many items to display.
The solution I came up with is something like this.
Basically, I want to add 1 to the array, but also remove 3; so the new array will be [1,2].
EDIT: sorry, but if this was a redux reducer, where I have to do everything in one line, how would I accomplish that?
const add = 1;
const state = [2,3];
const update = [add, ...state.filter((num, idx) =>{
return idx !== state.length - 1
})]
reducer sample:
return {
...state,
items: [add, ...state.filter((num, idx) =>{
return idx !== state.length - 1
})]
}
I might be overthinking it, and I have a feeling there is a much much cleaner way to write this..
What I also don't like is that I'm not even using the first argument in filter. It's just there so I can access the index..
You can use slice(). The negative ending index works backwards from end of array
const add = 1;
const state = [2,3]
const res = [add, ...state.slice(0,-1)]
console.log(res)
To remove the last element of an array use array pop method and to add an element to first position use array unshift method.
const add = 1;
const state = [2, 3];
state.pop();
state.unshift(add);
console.log(state);