how can i get the information inside react js object - reactjs

how can I access the name inside the object and put it inside a variable
const newItem = [...items].filter((item) => id === item.id);
const comments = newItem.price;
console.log([newItem.price]);
I tried this one but didn't work, console says undefined

The filter() method creates a new array with all elements that pass the test implemented by the provided function.
filter() method
You can get price by usign the below way.
const newItem = [...items].filter((item) => id===item.id);
const comments= newItem[0].price;
console.log(newItem[0].price)

Related

setState mutates the object reference

I am getting an object from parent component and setting to state. In child component I am updating the state, but the parent reference object values also changing instead of only state changes.
Parent Component has a huge object,
obj = {
values: {
per1: { name: "rsk" },
per2: { name: "ssk" },
}
}
Child Component:
const ChildComponent = ({obj}) => {
const [inp, setInp] = useState(obj.values);
const onChange = useCallback(({target}) => {
setInp((prev) => {
const nD = { ...prev };
//k1, k2 comes from some logic
nD[k1][k2] = target.value;
return nD;
})
}, []);
return (
Here the "inp" state is looped by objects and keys in text box to build a html form
)
}
Here the question is, why the core obj.values also changing on onChange setInp time. I dont want to disturb the obj.values untill i submit the form.
Because before submit the Form, I need to validate,
obj.values are equal or not to inp state values
Any idea on this.
The original object is changing because in JS, when you pass an array or an object in such a way, you are actually passing a reference to the original object/array.
Meaning that any changes made to the reference, will also affect the original.
In-order to avoid using the reference, you can copy the object/array and work with the copy instead.
There are a few ways of doing this, the simplest IMO is using the spread syntax.
Example:
const ChildComponent = ({obj}) => {
const [inp, setInp] = useState({...obj.values});
...
}
What we do here is "spread" the contents of obj.values into a new object, thus creating a new object and avoiding using the reference.
Note that the spread syntax only makes a shallow-copy, this isn't necessarily an issue unless you have some complex object which contains some other nested objects within it.
If you do need to perform a deep-copy, one simple way of doing it is via JSON methods.
Example:
const clone = JSON.parse(JSON.stringify(original));
First, this obj variable is incorrect because per1 is defined as object and object consist of key and value, but it is like a string array so please check that, and below is solution
In Child Component you should create a copy of that obj variable
const [inp, setInp] = useState(Object.assign({}, obj.values));
Bz if you set inp as the same variable it will pass the address of that variable so for that you need to create the copy and then you can change that inp.

Adding to a state array without the resulting array being read only, in React Native?

Im programming a component where I am mapping over a component using an array I have stored in state.
const [animalList, setList] = useState(['cat', 'dog'])
{ animalList.map((tag) => {
return (
<AnimalButton animalz={tag}/>
)
})
}
I want to add to the state array to force to make the app rerender. I attempted to do so with a .push function, store the increased array in a temporary variable and assign that new array to the state, as push() and unsplice don't return the actual array.
onSubmit={(values, actions) => {
actions.resetForm();
animalList.push(values.pet)
let newList = animalList
setList(animalList = newList)
}}
However I get this error [TypeError: "animalList" is read-only]?
Is there a way to change add to animalList without my resulting list in the state becoming read only?
Yes you cannot push this into const.
However, you can use this approach.
setList([...animalList,values.pet])

How to mutate an object inside array in react.js state?

I have an issue when i trying to updating the state.
here is my code:
const [todos, setTodos]= useState([])
useEffect(() => {
setTodos([
{id:1, title: '',
notes: [{id: 1, description: 'this is a simple description'}]}
])
}, [])
my goal is to add a note to the array of todos.
i try like this
const i = todos.findIndex((t) => t.id === parseInt(id));
const newArr = todos[i].notes[0].push(note);
setTasks(newArr);
but it's not working the newArr gives me the index note the new state.
Please help
Thanks in advance
if you want to get it working you can do something like below:
const newArr = todos[i].notes.push(note)
but it's not the recommended way.
The best way to add new item in to your notes array is to use object.assign or spread operator in order to not directly mutate your entire array. some thing like below:
const newArr = [...todos[i], note]
and also use this way of mutating your entire tasks array.
I think it's been well-described ar here if you want to get more information around why you should use spread operator instead of push.
I have created this which works perfectly. What you have to do is to obtain the todo id and push to its note. Here the todo state gets updated but render method is not called. In order to call the render method I have called setTodo again.

Adding an element to an existing array in react hooks

So I have this state variable:
const [Class, setClass] = useState({ Teacher: "John Fartsalot", Year: 2021, Students: [] });
and I have a:
ver studentObject
I want to push the studentObject into the Students array dynamically using setClass.
I came across this post: Push method in React Hooks (useState)? but it seems to be relevant only when there's just the list in there.
What is the correct way to do so in my case?
While you could spread the existing Class into a new object, and then spread the new students array into that new object as well, it would be better to follow the convention and separate out the state variables (as React recommends), and to not use Class as a variable name (it's very close to the reserved word class). Consider:
const [teacher, setTeacher] = useState('John Fartsalot');
const [year, setYear] = useState(2021);
const [students, setStudents] = useState([]);
Then to add to the students array, do
setStudents([...students, studentObject]);
Or, if students happens to be in a stale closure at this point, then
setStudents(students => [...students, studentObject]);
This is correct way to add:
setStudents(students => [...students, studentObject]);

Delete item from list not rendering react js

I am displaying table from API, so when I click to delete it should delete
Now it's deleting actually. but the problem is it's not rendering the output
Here is my code for that function
const delpersonHandler = index => {
const apiDel = api;
console.log(index);
api.splice(index, 1);
console.log(api);
setApi({ ...api, apiDel });
};
here is where i call that
<TableCell align="Justify">
<Button variant="outlined">Edit</Button>
<Button variant="outlined" onClick={() => delpersonHandler(id)}>
Delete
</Button>
</TableCell>
full code is available here
https://pastebin.com/u7fAefBH
React states are immutable hence doing api.splice(index, 1); does not work because you're directly affecting the React state.
api is an array but you're setting an object in the setApi setter function
the simplest way to do this is
const delpersonHandler = index => {
let oldApi = [...api] // new array containing api's elements
oldApi.splice(index,1);
setApi(oldApi);
};
Assuming you are working with functional components, the useState hook delivers two values, specifically the getter and setter of your state, invoking the last one with some parameter will set a new value and invoke a render call.
In the example, setApi is this setter method, but you are calling it with an object as parameter instead an array. And by using the splice method with the api value is possible to inferer that it must be an array. So you need to call the setter with the same variable type:
const delpersonHandler = index => {
// Don't apply changes directly, instead clone it and modify it.
const newApi = api.slice();
newApi.splice(index, 1);
// Pass an array instead an object
setApi(newApi);
};
I found the fix by using the below code
const delpersonHandler = index => {
const apiDel= [...api]; //getting the current state of array using spread operator
apiDel.splice(index, 1); //deleting based on index
setApi(apiDel);
console.log("state updated", api);
}
[...api] without this line this wasn't working

Resources