React - create recursive children - json

My issue is simple, i want to make a list from json recursively.
What i have by now:
const jsonMenuConfig =[
{
main:"Li1",
inside:[]
},
{
main:"Li2",
inside:[]
},
{
main:"Li3",
inside:[{main:"insideLi1",inside:[]},{main:"insideLi2",inside:[]},{main:"insideLi3",inside:[]}]
}
];
class App extends React.Component{
render(){
return(
<ListMaker tree={jsonMenuConfig}/>
);
}
}
function ListMaker(props){
return props.tree !== undefined || props.tree.length > 0 ?
<ul>{
props.tree.map((item)=>{
return <li>{
item.main
}{
<ListMaker tree={item.inside}/>
}</li>
})
}</ul>
: null
}
ReactDOM.render(
<App/>,
document.getElementById('app')
);
My main idea was to create function that could call itself and return deeper children only when children exist.
I think that should work but i cant rid of ul's inside all li's. It seems ul should never be rendered inside first and second li becouse it doesn't fit this
props.tree !== undefined || props.tree.length > 0
What is happening right now :
<ul>
<li>
<ul></ul> -- empty, should never return
</li>
<li>
<ul></ul> -- empty, should never return
</li>
<li>
<ul></ul> ... -- children here, succes
</li>
</ul>
What i simply want :
<ul>
<li></li>
<li></li>
<li>
<ul>
<li></li> ... -- children here, succes
</ul>
</li>
</ul>
What can be possible wrong ?
Can it be done better way ?

You have bad logic here. Change props.tree !== undefined || props.tree.length > 0 to props.tree !== undefined && props.tree.length > 0.
|| means or so if either condition is true it is going to evaluate to true and since props.tree is defined it is firing true.

Related

how to get value from json object with its index number in reactjs like posts[2].title

from https://jsonplaceholder.typicode.com/posts
{ this.state.posts.map((post) => {
return (
<li>
<span>{post.title}</span>
</li>
);
})
}
it return all the title but how do I get post[1] or post[0] title
tried {post[0].title} not working
Thank you
Remove the map function and simply write
<li>
<span>{this.state.posts[0].title}</span>
</li>
You can pass the index with post inside function, it will help us to iterate over list of post.
{this.state.posts.map((post, index) => {
<li>
<span>{post[index].title}</span>
</li>
})
}
return should be before the map if you need it.
return (
{this.state.posts.map((post, index) => {
<li>
<span>{post[index].title}</span>
</li>
})
}
)

How can I extract data from complex JSON file with reactJS?

I am new to reactJS. I have a JSON file which looks like this:
I want to extract data and display each post with its comments, user who commented and created time and display it with JSX using the map function.
So I declared an empty array called items in my state and put all these data into it and tried to browse it but I got this error:
×
TypeError: Cannot read property 'data' of undefined
this is my code:
render() {
return (
<div>
<h1>Hello World !!!! </h1>
<ul>
{ this.state.items.comments.data.map(item => <li key={item.id}>{item.data[item].from.name}</li>)}
</ul>
</div>
)
}
Nice to meet you.
I can solve it.
Please do like below.
render() {
return (
<div>
<h1>Hello World !!!! </h1>
<ul>
{ this.state.items.comments.data.map(item => <li key={item.id}>{item.from.name}</li>)}
</ul>
</div>
)
Please reply with your opinion.
Best regards.
in your json file look like you get array of array
try with this hope this will work
this.state.items.map((item,index)=>{
this.state.items[item].comments.data.map(element=>
<li key={item.id}>{item.from.name}</li>)
})
})
I figured out that I have to use map inside another map because I have an array in another array and this code solved the problem:
render{
return (
<div>
{
this.state.items.map((item) => {
return (
<div>
<h4>{item.id}</h4>
<ul>
{
item.comments.data.map((data) => {
return (
<li>
{data.message} : {data.created_time} : {{data.from.name}
</li>
);
})
}
</ul>
</div>
);
})
}
</div>
);
}

Using ngClass 'Missing expected }' error being received

I am trying to conditionally add a class to a list item (through a child components selector), depending on the images width size. The width size is hard coded when the new image item is created in another component.
I keep receiving the error message :
'Missing expected }' in my gallery-list.component.html file.
I can't see that I am missing } anywhere. Can anyone help?
Here is the gallery-list html code:
<ul class="container">
<li class="item-list-container" data-masonry='{ "itemSelector": ".grid-item", "columnWidth": 160 }'><app-image-item
class="image-item"
*ngFor="let imageEl of images;"
[image]="imageEl"
[ngClass] ="{
'widthOne': imageEl.widthSize === 50px,
'widthTwo': imageEl.widthSize === 100px,
'widthThree': imageEl.widthSize === 150px,
'widthFour': imageEl.widthSize === 200px,
}"
(click)="onImageSelect(imageEl.id)"
></app-image-item>
</li>
</ul>
That's not a correct syntax. Take a look at this similar demo. Try
<ul class="container">
<li class="item-list-container" data-masonry='{ "itemSelector": ".grid-item", "columnWidth": 160 }'><app-image-item
class="image-item"
*ngFor="let imageEl of images;"
[image]="imageEl"
[ngClass] ="getClass(imageEl.widthSize)"
(click)="onImageSelect(imageEl.id)"
></app-image-item>
</li>
</ul>
in ts file:
getClass(widthSize): string{
if(widthSize === "50px") {
return "widthOne"
}
if(widthSize === "100px") {
return "widthTwo"
}
if(widthSize === "150px") {
return "widthThree"
}
if(widthSize === "200px") {
return "widthFour"
}
}
Note:
I would recommend you to add a property on images array deciding the class which has to be added, rather than using function call as I did using getClass(). Using function on HTML is a bad practice.
If the image is coming from some service, you can use .map and add className property on it.

Cant onClick event do <li> tag React

I have a sideBar that opens when I click on a button and i have <li> items there.
I want do add an onCLick event to those items but, onClick event fires when page is loaded and when ever I click on <nav className={drawClass}> elements.
Any information is helpful, thank you.
const Sidedraw = props => {
let drawClass = "sideDraw";
if (props.show) {
drawClass = "sideDraw open";
}
return (
<nav className={drawClass}>
<ul>
<li className="matches" onclick={console.log("work work")}>
Pro matches
</li>
<li className="matches">Public mathes</li>
<li className="matches">Players</li>
<li className="matches">Teams</li>
</ul>
</nav>
);
};
As others have mentioned, the onClick should be a function reference.
Also, you will likely get a warning with the current code:
Non-interactive elements should not be assigned mouse or keyboard event listeners
You should place an interactive element (anchor, button, etc.) within the list item.
<ul>
<li className="matches">
<button onClick={() => console.log('work work')}>Pro matches</button>
</li>
<li className="matches">Public mathes</li>
<li className="matches">Players</li>
<li className="matches">Teams</li>
</ul>
You’re setting the onClick to the result of the console.log call, not the function itself. You want:
onClick={() => console.log("work work")}
Check out the docs for Handling events.
Also, you might want to move your click handler into its own function so that you can easily add it to all nav items.
const Sidedraw = props => {
let drawClass = "sideDraw";
if (props.show) {
drawClass = "sideDraw open";
}
function clickHandler(evt) {
console.log(evt.target)
}
return (
<nav className={drawClass}>
<ul>
<li className="matches" onClick={clickHandler}>Pro matches</li>
<li className="matches" onClick={clickHandler}>Public mathes</li>
<li className="matches" onClick={clickHandler}>Players</li>
<li className="matches" onClick={clickHandler}>Teams</li>
</ul>
</nav>
);
};
Stackblitz
you must add clickeventhandler to each element you want to perform some actions.
<li className="matches" onClick={handleValueChange}>Pro matches</li>
and you must add that function ie
handleValueChange = (e) => {
// ...
}

Umbraco & Razor. Filter selection by dropdown value

I have a selection generated from the children of the current page. Within that selection (let's call it Fruit) I have items and each item has a fruitType.
This code doesn't work:
#{
var selection = CurrentPage.Children("fruit").Where("Visible");
}
<ul>
#foreach(var item in selection){
#if(#item.fruitType == "Apple"){
<li>
#item.Name<br/>
#item.fruitName<br>
#item.fruitType<br>
#if (item.image != null && !(item.image is Umbraco.Core.Dynamics.DynamicNull))
{ var m = Umbraco.Media(item.image);
<img src="#m.Url" alt="Picture of #item.Name" />
}
</li>
}
}
</ul>
What I'm trying to do is to only list the items with a fruitType of "Apple". This value is selected from a "fruitType" dropdown list and I've tried using both the numeric and string values that Umbraco uses from Dropdown datatypes.
It all works perfectly if I remove the if conditional except that it displays all fruit types.
Any suggestions?
sigh Just one too many declarations..
Turns out neither the if nor the item references need the additional # declaration in front of it so the correct code looks like:
#{
var selection = CurrentPage.Children("fruit").Where("Visible");
}
<ul>
#foreach(var item in selection){
if(item.fruitType == "Apple"){
<li>
#item.Name<br/>
#item.fruitName<br>
#item.fruitType<br>
#if (item.image != null && !(item.image is Umbraco.Core.Dynamics.DynamicNull))
{ var m = Umbraco.Media(item.image);
<img src="#m.Url" alt="Picture of #item.Name" />
}
</li>
}
}
</ul>