Reputation: 13
React newb here. When props.submitClk === true (the green light that my upload button has been clicked and a file is sent from another component's form) , I'm trying to update state setList with a new technique object, but for now just, 'SomeObject'. I then get a "TypeError Can't read property 'map' of undefined" after click. I tried messing around with some conditionals, but no luck after a few hours of trying. Is this a async issue and the map is happening too soon? handleRemove works fine when I'm deleting objects. If I remove the function under the if statement, it will not throw an error on form submit. Also, the object is going to be larger, that it is why its currently nested this way. Thanks for any answers.
function SampleData(props) {
const [list, setList] = React.useState( [
{
closedguard: [
{
name: "Armbar",
link: "",
x: "X",
id: "1",
},
{
name: "Triangle",
link: "",
x: "X",
id: "2",
},
{
name: "Omaplata",
link: "",
x: "X",
id: "3",
},
] }
] );
if( props.submitClk === true) {
setList([...list, 'SomeObject'])
}
const handleRemove = (id) => {
const newList = list[0].closedguard.filter(move => move.id !== id);
setList([{ closedguard: newList }]);
};
return (
<div className="guard">
<ul className="techUl">
{" "}
Closed Guard
{list.map((pos) =>
pos.closedguard.map((move, id) => (
<li
key={id}
className="techLi"
>{move.name}
<span onClick={(id) => handleRemove(move.id)}> {move.x}</span>
</li>
))
)}
</ul>
</div>
);
}
Upvotes: 1
Views: 128
Reputation: 209
for updating the closeguard array of ur state list
u can see @Nafis answer but u
should make use of useEffect hook for running sideeffects. try putting this logic coupled with @Nafis answer for updating the state -
if( props.submitClk === true) { setList([...list, 'SomeObject']) }
inside an useEffect hook like shown below
useEffect(()=>{
if( props.submitClk === true) {
setList([...list, 'SomeObject']) }
},[list])
Now modify the list.map function as below, then u wont get map undefined error
{list.length > 0 && list.map((pos) =>
pos.closedguard.map((move, id) => (
<li
key={id}
className="techLi"
>{move.name}
<span onClick={(id) => handleRemove(move.id)}> {move.x}</span>
</li>
))
)}
let me know if it works or not
Upvotes: 1
Reputation: 4561
If you wanted to update the nested object to add elemets to your closedguard:
property array, check @Nafis answer.
What I believe is the problem is that the new objects you add do not have the closedguard
property, so the map function cannot map that object.
If you add an object with that property it will work, for example:
const objToAdd = {closedguard: [
{
name: "newObj1",
link: "",
x: "X",
id: "3",
},
{
name: "newObj2",
link: "",
x: "X",
id: "3",
}]
}
If what you are doing is adding objects with another property, what you might need to map is the corresponding key, to be sure that you are getting a property out of the object, so would need to channge
pos.closedguard.map((move, id) => (
by:
pos[Object.keys(pos)[0]].map((move, id) => (
for example.
So in case your object doesnt have the closedguard
, the first property of that object would be mapped.
Posting the full return with my proposal just to leave my proposal clear:
return (
<div className="guard">
<ul className="techUl">
{" "}
Closed Guard
{list.map((pos) =>
pos[Object.keys(pos)[0]].map((move, id) => ( //CHANGE HERE
<li
key={id} className="techLi"
>{move.name}
<span onClick={(id) => handleRemove(move.id)}> {move.x}</span>
</li>
))
)}
</ul>
<button onClick={handleOnClick}>Button</button>
</div>
);
Upvotes: 0
Reputation: 1030
First without someObject
you'll face Too many re-renders. React limits the number of renders to prevent an infinite loop.
Then you're updating nested object:
[
{
closedguard: [
{
name: "Armbar",
link: "",
x: "X",
id: "1",
},
{
name: "Triangle",
link: "",
x: "X",
id: "2",
},
{
name: "Omaplata",
link: "",
x: "X",
id: "3",
},
]
}
]
array of object, then object closedguard
is inside which is an array.
So what you can do inside condition is
// think is the some objects
const newObject = [
{
name: "test1",
link: "",
x: "X",
id: "5"
},
{
name: "test2",
link: "",
x: "X",
id: "56"
}
];
setList([{ closedguard: [...list[0].closedguard, ...newObject] }]);
instead of
setList([...list, 'SomeObject'])
Upvotes: 1