I have an objective to make a ponent, that renders cards with nested ul tags like this: from data like this, that's being passed down with props from a parental ponent:
For that I set markers at the end of the lines where the nested ul should start, e.g. ":" when the nested ul should open and "." when the nested ul should close. But to make this code work, I need to render opened, but not closed tags.
let inUl = false;
<div className="cardBody">
{props.body.map((el, index) => {
if(el.endsWith(":")){
inUl = true;
return <li>{el}<ul>
} else if(inUl && el.endsWith('.')){
inUl = false;
return <li>{el}</li></ul>
} else {
return <li>{el}</li>
}
})}
</div>
Any help will be greately appreciated, I've a close deadline, and right now I'm literally stuck on the last part of the project - this.
I have an objective to make a ponent, that renders cards with nested ul tags like this: from data like this, that's being passed down with props from a parental ponent:
For that I set markers at the end of the lines where the nested ul should start, e.g. ":" when the nested ul should open and "." when the nested ul should close. But to make this code work, I need to render opened, but not closed tags.
let inUl = false;
<div className="cardBody">
{props.body.map((el, index) => {
if(el.endsWith(":")){
inUl = true;
return <li>{el}<ul>
} else if(inUl && el.endsWith('.')){
inUl = false;
return <li>{el}</li></ul>
} else {
return <li>{el}</li>
}
})}
</div>
Any help will be greately appreciated, I've a close deadline, and right now I'm literally stuck on the last part of the project - this.
Share Improve this question asked Oct 15, 2018 at 7:10 SthSth 5421 gold badge10 silver badges22 bronze badges 3- 1 Wele to Stack Overflow! Please have a look around, and read through the help center, in particular How do I ask a good question? Post code, markup, data strings, and other text as text, not as pictures of text. Why: meta.stackoverflow./q/285551/157247 – T.J. Crowder Commented Oct 15, 2018 at 7:11
-
1. I don't see any
:
or.
that explains your code in the data you are showing us, so it's not easy to see what would be the solution, but for what I understand @0xc14m1z's answer sounds good to me. Truth is : there are not any opened tags in React, nor in HTML. If you really think about opened tags, you are probably making a mistake in the way you think your data parsing. – arnaudambro Commented Oct 15, 2018 at 7:43 - Probably you're right, maybe I chose the "open/close" tag option, because couldn't find a good way for initial data organisation. Right now trying that with @0xc14m1z's answered variant. Although the code is without any semicolons, a bit hard to read. – Sth Commented Oct 15, 2018 at 7:47
2 Answers
Reset to default 5But to make this code work, I need to render opened, but not closed tags.
This is a fundamental misunderstanding of how React works. You use tags in the source code to define elements, which are objects. You can't have an opening tag without a closing tag any more than you can have an opening {
for an object initializer without a closing }
.
Instead, you have a ponent that you pass children to, and it renders the children within its ponent. E.g.:
const UnorderedList = props => <ul>{props.children}</ul>;
...which is used like this (i.e., in a render
somewhere):
return <UnorderedList><li>...</li><li>...</li></UnorderedList>;
You shouldn't think in term of open or closed tags...
To achieve your result, I would BEFORE reorganize the data in a data structure that could be easily rendered, something like this:
const elements = [
"first ul:",
"first li",
"second li",
"third li.",
"second ul:",
"first li",
"second li",
"third li.",
"third ul:",
"first li",
"second li",
"third li."
]
const makeUls = elements => {
const uls = {}
let currentUl
elements.forEach(element => {
if ( element.endsWith(":") ) {
uls[element] = []
currentUl = element
} else {
uls[currentUl].push(element)
}
})
return uls
}
Calling makeUls
and giving the flat array, you should have a map like this:
Object {
"first ul:": ["first li", "second li", "third li."],
"second ul:": ["first li", "second li", "third li."],
"third ul:": ["first li", "second li", "third li."]
}
Once you have this kinda structure, you can easily render everything properly:
render() {
const uls = makeUls(props.body)
Object.keys(uls).map(ul => (
<ul>
{ uls[ul].map(li => <li>{ li }</li> }
</ul>
))
}
Consider to properly add key
attribute and everything.