how to render array in object in array? (react) - reactjs

const checked = [{
food:['apple', 'banana']
drink:['wine', 'beer']
}];
render (
<>
{checked.map((value) => {
value.food.forEach((each) => (
<div>{each}</div>
)
)}
</>
)
I tried this way and noting is shown in browser..
what would be the best way to approach?

Need to Return Your data like below!!
import React from "react";
export default function App() {
let checked = [{
food:['apple', 'banana'],
drink:['wine', 'beer']
}];
return (
<div className="App">
{
checked.map((item) => {
return item.food.map((fruit)=>{
return <h1>{fruit}</h1>
})
})
}
</div>
);
}

Your code has multiple errors.
It should be render instead of rander
While defining object, multiple properties should be separated using a comma. So put comma after the food array.
forEach doesn't return any thing. It just iterates over an array. So, if you want to return something (in this case a div element), use map.
Also, you should use key for each div element otherwise react would give you a warning in the console. This is done so that while re-rendering, based on the keys, react would understand which component to re-render and which to skip. Otherwise all the div would be re-rendered which is a costly operation.
const checked = [
{
food: ["apple", "banana"],
drink: ["wine", "beer"]
}
]
return (
<>
{checked.map((value) => {
return value.food.map((each, index) => {
return <div key={index}>{each}</div>;
});
})}
</>
);

There is a couple of improvements that require to be implemented to make the list displayed.
First, the map method does not return anything.
Two solutions:
Remove the curly brackets checked.map((value) => value...
Add a return keyword: checked.map((value) => { return value...}
The other issue is that the second loop is iterated using the forEach method.
The difference between the two (forEach and map) from MDN:
The forEach() method executes a provided function once for each array
element.
MDN
The map() method creates a new array populated with the results of
calling a provided function on every element in the calling array.
MDN
Basically, it means that forEach does not return anything and that why you need to use map
checked.map((value) => {
return value.food.map((each) => (<div>{each}</div>))
})}
or
checked.map((value) =>
value.food.map((each) => (<div>{each}</div>))
)}

You are iterating over the checked array items using forEach which won't induce any results since the forEach method
executes a provided function once for each array element.
which won't result in a transformed array.
What you are looking for is the map method which
creates a new array populated with the results of calling a provided function on every element in the calling array.
hence returning your transformed items so that they can be rendered (transformed at compilation time to ReactElement using the JSX syntax).
Note that you need to use an HTML tag instead of a React.Fragment the empty tag <> syntax:
const checked = [{
food:['apple', 'banana'], // there is a missing comma here
drink:['wine', 'beer']
}];
render ( // render and not rander
<div> // div instead of empty tag
{checked.map((item) => item.food.map((each) => <div>{each}</div>))}
</div>
)

Can check this approach. if you want to print just food values, below code should work. If you want to print all the values (both food and drink), then uncomment the commented code below.
export default function App() {
const checked = [
{
food: ["apple", "banana"],
drink: ["wine", "beer"]
},
{
food: ["grapes", "oranges"],
drink: ["coke", "sprite"]
}
];
// to display values of all arrays.
// return (
// <>
// {checked.map((value) => {
// const keys = Object.keys(value);
// return keys.map((eachKey) => {
// return value[eachKey].map((individualValue) =>
// (
// <div>{individualValue}</div>
// )
// )
// });
// })
// }
// </>
// );
// To display just food values.
return (
<>
{checked.map((value) => {
return value.food.map((each) => <div>{each}</div>);
})}
</>
);
}

Related

How can I handle the value of array or data in json file?

I'm making checkbox function using data in json file.
I want to show 'O' and 'X' according to the value called checked in json file.
And want checked value changed when 'O' or 'X' is clicked.
For this, I tried to make handleCheck function but it doesn't work.
May I know which part is wrong and how to modify it?
App.js
import "./styles.css";
import dummy from "./database/data.json";
export default function App() {
const handleCheck = (number) => {
dummy.state[number].checked !== dummy.state[number].checked;
};
return (
<div className="App">
{dummy.state.map((item, idx) => {
return (
<div
onClick={() => {
handleCheck(item.id);
}}
key={idx}
>
{item.checked ? "O" : "X"}
</div>
);
})}
</div>
);
}
data.json
{
"state": [
{
"id": "1",
"checked": true
},
{
"id": "2",
"checked": true
},
{
"id": "3",
"checked": true
}
]
}
codesandbox
https://codesandbox.io/s/serene-forest-j0cb25?file=/src/database/data.json:0-176
You're running into some JavaScript syntax issues and React-specific issues.
One of them is that you're modifying the JSON file array directly, and React isn't going to re-render on those changes. A way to fix this would be to use the useState hook with your dummy data as the initial state. You can accomplish this like so:
const [data, setData] = useState(dummy.state)
Now, we have a data variable which corresponds to your dummy data's state array and a setData function which will let us set data to whatever value we'd like and have React re-render the UI.
The next bit we need to tackle will be to make sure the handleCheck function is updating our useState's data variable and setting it correctly. We have two big issues right now with this function.
First, you're really close to flipping the checked value, but the o.checked !== o.checked is doing a comparison instead of setting your variable; basically, the code is asking "is X strictly not equal to X?" MDN has a great page on what strict inequality is. What we'd like to do is set A.checked to "not A.checked". To fix this, we can do item.checked = !item.checked.
Additionally, calling dummy.state[number].checked doesn't point to what you probably think it will since your IDs are keys on an object. If number = 1, then dummy.state[1] actually ends up being the second item in the array, because JavaScript arrays are 0-indexed. Instead, we can update the function like so
const handleCheck = (id) => {
setData(
data.map((item) => {
return item.id === id
? { ...item, checked: !item.checked }
: { ...item };
})
);
};
Now what we're doing is using the map function to loop over your data, destructure it (arrays are references, and we don't want to mutate the "old" data), and conditionally change the checked property based on if the item's ID matches the ID passed into handleChecked.
I've forked and updated your CodeSandbox so you can see it all put together in App.js.
First you need to move the json data to a state value and update the state value accordingly and at the end you can push the json data out
import "./styles.css";
import dummy from "./database/data.json";
export default function App() {
const [data,setData]=useState(dummy.state)
const handleCheck = (number) => {
setData(state=>{
let newState=[...state]
newState[number].checked = !state[number].checked;
return newState
}
};
return (
<div className="App">
{data.map((item, idx) => {
return (
<div
onClick={() => {
handleCheck(item.id);
}}
key={idx}
>
{item.checked ? "O" : "X"}
</div>
);
})}
</div>
);
}
The data state value have the correct values and you can use them accordingly

How to Iterate and Get React State Object Values?

Here is my simple react component.
export default function App() {
const [stats, setStats] = React.useState(() => {
return {
name: "",
lvl: 1
}})
let displayStats;
for(let key in stats) {
displayStats += <p>{key}</p>
}
return (
<>
{displayStats}
</>
)
}
This displayStats variable returns 'undefined[object Object][object Object]' on the screen. Why? What am I doing wrong.
Change your code to this
return (
<>
{Object.keys(stats).map(key => <p>{key}</p>)}
</>
)
-> If you want to iterate through only values use Object.values(objName)
-> If you want to iterate through both values and keys use Object.entries(objName)
Try using the key on the stats object.
Change
displayStats += <p>{key}</p>
To
displayStats += <p>{stats[key]}</p>

Removing an element in an array and then using map to make it dynamic React

I want to remove an element from the array arradd. Currently, I am able to use the id which is in incremented order and remove the element with the help of splice. However, this method is not dynamic since it does not return the map immideately. How do I make this dynamic?
const handleremove = (e) => {
arradd.splice(e.target.id, 1);
}
return(
{arradd.map((a, idx) => {
return <div key={a}>
<HoriContainer><Texty>{a}</Texty><img id={idx} idx={idx++} onClick={handleremove}src=
{cross}></img></HoriContainer>
</div>

Loop array into html from setconstant react

I'm new to react, please don't mind on my questioning format.
I am trying to render an array into html. Stuck in rendering.
const getFullData= (prop: string, filter_data?: any) => {
let final_array: any = []
// here my code does some looping and some functionality and pushing the data into above array
//array will be after pushing the data [" text1","text2"]
setfilterConst({...abc,test:final_array})
}
<div class="row">
{ReactHtmlParser(abc.test)}
</div>
but coming with "," . I want to loop and render
Take your array a do a reduce, acc is the variable that is going accumulate (in this example) Cards, when the full loop is done, it is going to set it in the content state, then use <>{content}</> at the rendering part.
data is your array
setContent(
data.reduce((acc, ele) => {
let content = ele.content
let title_name = ele.name
acc.push(
<Card
title={title_name}
className="components_card"
key={shortid.generate()}
>
{ReactHtmlParser(content)}
</Card>
);
return acc;
}, [])
);
Since you are computing and storing an array of JSX you will need to map this array when rendering, passing each element into the ReactHtmlParser utility.
const getFullData= (prop: string, filter_data?: any) => {
const final_array: any = [];
// here my code does some looping and some functionality
// and pushing the data into above array.
// array will be after pushing the data:
// ["text1", "text2"]
setfilterConst(abc => ({ ...abc, test: final_array }));
}
...
<div class="row">
{abc.test.map((link, index) => (
<React.Fragment key={index}>
{ReactHtmlParser(link)}
</React.Fragment>
))}
</div>
That being said, it's actually anti-pattern in React to store JSX into component state. You will not want to make a habit of doing this. Instead you should store the data that represents your UI and map to the JSX in the render. Note here that since you are mapping the data to JSX instead of an HTML string you won't need to parse it into renderable HTML.
const getFullData= (prop: string, filter_data?: any) => {
const final_array: any = [];
// here my code does some looping and some functionality
// and pushing the data into above array
// array will be after pushing the data:
// [{ text: "text1", href: "#" }, { text: "text2", href: "#" }
setfilterConst(abc => ({ ...abc, test: final_array }));
}
...
<div class="row">
{abc.test.map(({ href, text}, index) => (
<a key={index} href={href}>{text}</a>
))}
</div>

React - Iterating over State to dynamically generic element

This is a pretty basic question but I've been struggling; Likely due to my 'not quite understanding' how .map() works, and when to make an Object an array etc.
import React, { Component } from 'react';
import Post from './Post/Post';
class Posts extends Component {
state= {
posts: [
{
title: "Test",
content: "Some content"
},
{
title: "Test2",
content: "Some Additional Content"
}
]
};
render() {
let post = null;
post = Object.keys(this.state.posts).map(function (item, key) {
return <Post title={this.state.posts[item].title} content={this.state.posts[item].content} />
})
return (
<div>
<div>List of Posts</div>
{post}
</div>
);
}
}
export default Posts;
This is where I settled, since I got my JSBin version to work. However I'm getting a warning on my 'anonymous callback' function that creates the <Post> elements. <Post> is just expecting those two props and rendering them. I'm getting a warning on line 26 that mentions state being undefined. Am I not initializing state properly?
post = this.state.posts.map(function (item, key) {
return <Post title={item.title} content={item.content} key={key}/>
})
Your state.posts is an array and you should map over it.
post = Object.keys(this.state.posts).map((item, key) => {
return (
<Post
title={this.state.posts[item].title}
content={this.state.posts[item].content}
/>
)
})
as Subin says, what you need to do in that case is just map over the posts array.
But, to fix your code is very simple. just use arrow function instead of a regular function.
Do it like this:
post = this.state.posts.map(post => {
return <Post title={post.title} content={post.content} key={post.title}/>
})
When you map over array, you dont need to acces that state again, because post will be assigned to post inside map function. And then just acces title and content. and dont forget to pass key,there i've passed key={post.title} but that is not a good solution, because it needs to be unique.

Resources