How to assign an object from an array to an arrow function? - javascript

I am trying to assign a variable with the properties of an object from an array in my redux state. I am trying to loop through the array of objects and assign the variable when the ID of the item matches up to the ID that I am searching for.
I have been trying anything I can from nested if statements, multiple returns, I cannot seem to figure this out.
Currently, this is what I have.
const currItemProps = () => {
this.props.todos.find((todo) => {
(todo.id === this.props.itemID) ?
{ todo } : null
}
);
};
todos is my array I am searching for and the itemID is the ID I am lookking for (both are pieces of redux state).
I am trying to open a modal on the press of a todo that has the properties of the todo. Hence I am trying to assign a variable in my modal file with all of the properties of its current todo (the object from the array).

The find function expects that you'll return True when you find your item.
also, you need to specify a 'return' statement.
const currItemProps = () => {
return this.props.todos.find((todo) => todo.id === this.props.itemID);
};

In case you directly want to return model
const currItemProps = () => {
this.props.todos.find((todo) => {
(todo.id === this.props.itemID) ?
<ComponentName todoProps={todo}/> : null
}
);
};
then you can use the same in render method like {currentProps}

Related

How to update an item in an array of an object

I have a list of people, each with an id. I have to add a tag to a newly created array for a person with a certain id. The json object 'students' already exists and I am updating it using its useState setStudents method but it seems to be returning an unidentified object back. My plan was as follows:
Map through the previousStudents
If the id matches (the person who I'm adding a tag to), then add the tag. The if statement to add a tag is there because the 'tags' property doesn't initially exist, so I make it on the first tag add
If the id doesn't match, just return that student
const updateStudent = (tag, id) => {
setStudents((prevStudents) => {
prevStudents.map((student) => {
if (student.id !== id) return student;
if (student.tags) {
student["tags"].push(tag);
} else {
student["tags"] = [tag];
}
return student;
});
});
};
Sorry if my explanation was confusing but tldr: I'm just trying to add an item to an array of a specified object and it doesn't seem to be working.
A "cleaner" approach would be something like this:
const updateStudent = (tag, id) => {
// form a new students object
let newStudents = students.map(student => {
if(student.id === id) {
student.tags? student.tags.push(tag) : student.tags = [tag];
}
return student;
});
setStudents(newStudents); // set the newly formed object to state
}
It is better to separate the update logic from setting the state

Filter Inside UseEffect React Not Working

Im using the .filter() method on an object inside of a useEffect() method to filter out certain arrays out by name if they exist in a second object. I need to get the difference of arrays back into a useState() method. Im using the following and works outside the useEffect() method:
useEffect(() => {
getDBData().then( (r) => { setAnotherObj(r); });
getAPICall().then((r) => {
let result = r.filter(
(o1) => !anotherObj.filter((o2) => o1.name === o2.name)
);
setOption(result);
});
}, []);
Now that works outside of the useEffect method when I add it to an event like onClick, but not inside, it might work one time then it doesn't at all. What am I missing about the useEffect method that I need to know why the filtering isn't being done?
Replace second filter with find.
!anotherObj.filter(o2 => o1.name === o2.name) will always return false, be it has elements or not.
There is no dependency array in the in the useEffect, so whenever there is a state change, this useEffect gets triggered again.
Finding A-B, filter all the elements of A that are not in B.
r.filter(o1 => anotherObj.find(o2 => o1.name !== o2.name)); With this it removes all the elements that are common in A and B. And leaves out only elements in A.
Update as follows,
useEffect( () => {
getAPICall().then( (r) => {
const result = r.filter(o1 => anotherObj.find(o2 => o1.name !== o2.name));
setOption(result);
});
}, []);

When pushing a new value inside an array it gets totally override - VUEX

Hello so I am creating a filter search and I 'm trying to collect all the key (tags) that the user press, inside an array, however every time that a new value is push it does override the entire array. So I tried a couple of things, like spread syntax, concat, etc. But with no luck.
So my action looks like this:
const setCurrentFilters = async (context, payload) => {
if (payload) {
context.commit('setCurrentFilter');
}
}
My state
state:{
filters: JSON.parse(sessionStorage.getItem('currentFilters') || '[]'),
}
The mutation
setCurrentFilter(state, payload) {
state.filters.push(payload);
sessionStorage.setItem('currentFilters', JSON.stringify(payload));
}
And my getter
currentFilters(state) {
return state.filters;
},
Thank you in advance for any help : )
This is simply because you set const filters = []; which means that the next condition if (filters.length) will always return false (as you just created this array) and therefore the else statement will execute.
in the else statement you basically push the new payload to the empty array you just initialized - which makes your array always hold only the new value
i believe that you just need to remove the const filters = []; line, and access the filters property that exists in your state

Reactjs filter state by key and value

React Newbie here.
I'm trying to match the value of a specific id located in my state, so I can change some value before updating the database via my api.
The state is
state = {
library: []
}
and then with when the axios changes the state the array looks something like:
0:{_id:"", time:"", value:""},
2:{_id:"", time:"", value:""}
When I run console.log, it reads it like this.
(2) [{…}, {…}]0: {_id: "5c82803ad634ea0bebfb3eff", time: "2019-03-08T14:46:18.663Z", value:""}1: {_id: "5c827fb9d634ea0bebfb3efe", time: "2019-03-08T14:44:09.818Z", value:""}
So basically when I type in a specific input field, identified by it's _id, I need to update the value state of that specific state.
Here's the code I have written so far. _id is the unique key of the input field and event value what I'm typing.
updateRead = (_id, event) => {
console.log(_id);
console.log(event.target.value)
this.setState(?????)
};
Help would be much appreciated!
Cheers
You can use the array map method on the library array in your state, and just return the elements as is if the _id doesn't match, and update the value if the _id does match.
updateRead = (_id, event) => {
const { value } = event.target;
this.setState(prevState => ({
library: prevState.library.map(read => {
if (read._id !== _id) {
return read;
}
return {
...read,
value
};
})
}));
};
Two of the fundamental rules of state in React are:
Never modify state directly
Use the callback version of setState when you're setting state based on existing state (more)
Separately, you can't access properties on the synthetic event after the event handler has returned, so you'll want to grab the value before calling setState (since the call to your callback will be asynchronous).
Within the callback, you copy the array, find the relevant object, copy it, and set the value.
So:
updateRead = (_id, event) => {
const {value} = event.target;
this.setState(({library}) => ({
library: library.map(entry => entry._id === _id ? {...entry, value} : entry)
}));
};
map creates a new array from the previous array's entries. The callback returns a new object if the IDs match (using property spread notation) with an updated value, or the original object (since we don't have to copy objects we aren't modifying).

Error: Attempting to set key on an object that is immutable and has been frozen

I am having a rather hard time tracking down the issue related to this error, obviously the implication is I'm trying to update an immutable object. Oddly, I have used this implementation before without a hitch which is why I am finding this behaviour so perplexing.
Below is the method I am using, it simply alters the object of an array, changing the property and returns the updated state. As referenced here, using prevState appears to be the optimal way for getting around immutability.
onCheck = (id) => {
this.setState((prevState) => {
prevState.options[id].checked = !prevState.options[id].checked;
return {
options: prevState.options,
dataSource: prevState.cloneWithRows(prevState.options)
};
});
}
I have also tried a number of variations of copying the prevState, however it is still giving me the same immutability error. It appears as if it still references rather than duplicates the prevState.
onCheck = (id) => {
this.setState((prevState) => {
let options = [...prevState.options];
options[id].checked = !options[id].checked;
return {
options: options,
dataSource: this.state.cloneWithRows(options)
};
});
}
I eventually found a solution, it appears I needed to copy not just the array but each element of the array. As the individual elements / objects of the array are still immutable / frozen.
onCheck = (id) => {
this.setState((prevState) => {
const newOptions = prevState.options.map((option, index) => {
let copyOption = {...option};
if (id == index) {
copyOption.checked = !copyOption.checked;
}
return copyOption;
});
return {
options: newOptions,
dataSource: this.state.dataSource.cloneWithRows(newOptions)
};
});
}
In your question, you acknowledge that you are mutating the state, which you cannot do. A fix for this is to clone prevState.options before fiddling with it.
eg.
var options = Object.assign({}, prevState.options)
options[id].checked
return {
options,
...
As your reference pointed out, you should not directly mutate your data like you do
prevState.options[id].checked = !prevState.options[id].checked;
In your link, they return a new array by concat or by "spread syntax" (...). So i suggest you to copy your prevState first and mutate it
let state = [...prevState.options];
state[id].checked = !state[id].checked;
...

Categories