Generating Handlebars from a React Abstract Syntax - reactjs

As a proof of concept, I'm trying to generate Handlebars code from a simple React component. For example, I'd like to transform something like this.
import React from 'react';
const HelloWorld = ({ name, items }) => {
return (
<h1>
Hello {name}!
<ul>
{items.map((item, i) => (
<li key={i}> {item} </li>
))}
</ul>
</h1>
)
}
export default HelloWorld;
To something like this.
<h1>
Hello {{ name }}!
<ul>
{{#each items}}
<li key="{{#index}}">{{ this }}</li>
{{/each}}
</ul>
</h1>
My original idea was to use babel, typescript or another AST generator to generate an AST and then traverse it building out the handlebars output. Starting with the default export, traversing the nodes and outputting the return JSX Statements into a resultant string. Has anybody seen something similar where a handlebars template is generated programmatically?

Related

how to add :before css conditionally react

i want to conditionally add :before css selector to my dynamic product, currently its mutual fund but it can be later in future, please let me know how to do it
<div className={`${style.right_block}`}>
<ul className={`${style.three_points}`}>
<li className={`${style.mutual_fund}`} >{current_web.cat}</li>
<li className={`${style.beginner_icon}`}>{current_web.difficulty}</li>
<li className={`${style.time_icon}`}>{current_web.dur}</li>
</ul>
</div>
as you can see my product, difficulty, and dur(duration ) coming from api,
i want to chnage product :before icon based on my product,
If I understand the question correctly, you would like to conditionally add a :before css rule to a certain element?
<div className={`${style.right_block}`}>
<ul className={`${style.three_points}`}>
<li className={(yourCondition ? style.nameOfStyleInCssFileWithBeforeRule : style.normalStyle)} >{current_web.cat}</li>
<li className={`${style.beginner_icon}`}>{current_web.difficulty}</li>
<li className={`${style.time_icon}`}>{current_web.dur}</li>
</ul>
</div>
I recommend to use useState:
const [ConditinClass , setConditinClass] = useState(styles.NoBeforeStateMent);
Then to style your component :
<div className={ConditinClass} >
... your stuff
</div>
And to switch to class with before :
setConditinClass(styles.classWithBefore)
Be sure to create both classes.

How to get length by children collactions with Cypress?

I use Cypress.io with ReactJs
i have the html structure
<ul class="wrapper">
<li class="class-1">1</li>
<li class="class-2">2</li>
<li class="class-3">3</li>
<li class="class-4">4</li>
<li class="class-5">5</li>
</ul>
How can i get length of li elems?
like this document.querySelector(.wrapper > li).length
cy.get('.wrapp > li').length does not work
Like it is said in Cypress docs
cy.get('.wrapper li') // this yields us a jquery object
.its('length')
.then(length =>{
//code that uses the length
})
You can use something like:
cy.get('.wrapper').find('li').its('length').then((len) => {
//Do stuff with length
expect(len).to.equal(5)
})

Line 50: Parsing error: Unterminated JSX contents

Parsing Error: Unterminated JSX contents. Not sure why it keeps on saying that I need another tag. Also, the one thing that I have trouble with is what to do with the self-closing HTML tags. I don't know what to do with them for JSX.
I have tried to match all of the tags and used Atom to create an Html file and a bracket matcher. I have no idea why it keeps giving me this error. I thought to add a starting tag for the self-closing tags.
import React from 'react';
import linkedinIcon from "./footer-component/linkedin-icon.png";
export default class Resume extends React.Component {
render(){
return (
<div className="container">
<div className="col-md-12">
<h1>Résumé</h1>
<h3>SUMMARY</h3>
<p>Passionate front-end web developer with 3 years of experience using JavaScript, HTML5, CSS, Bootstrap and Javascript frameworks to build the users experience and user interface for client-facing webpages. Specializes in React, HTML, Bootstrap,
and CSS</p>
<hr>
</hr>
<h3>Technical Skills</h3>
<ul>
<li>Front-end</li>
<ul>
<li>HTML</li>
<li>CSS</li>
<li>Bootstrap 4</li>
<li>JavaScript</li>
<li>jQuery</li>
<li>Embedded JavaScript</li>
<li>REACT</li>
</ul>
<li>Other</li>
<ul>
<li>Git</li>
<li>GitHub</li>
</ul>
</ul>
<h3>Work Experience</h3>
<p>Operations Summer Intern, Benetech | Palo Alto, California | 2019 - 2019</p>
<ul>
<li>Created more than 20 landing pages in HTML5, CSS3, and Bootstrap 4</li>
<li>Implemented CSS/Bootstrap to design multiple responsive web pages</li>
<li>Maintained front-end code and documentation standards</li>
</ul>
<hr>
</hr>
<h3>Education</h3>
<div className="row">
<div className="col-md-2">
Expected in 06/2020
</div>
<div className="col-md-10">
<p><b>High School Diploma</b>
<br></br>
<b>Fusion Academy</b> - Palo Alto</p>
</div>
</div>
);
} // END OF RENDER
} // END OF Resume
Parsing error: Unterminated JSX contents. Hope errors are gone.
You didn't close two top div elements (.container and .col-md-12)
You are missing two </div> tags at the end for .container and .col-md-12.
Also, you should probably use <hr /> only, without the closing tag. HTML says:
Start tag: required, End tag: forbidden
<hr></hr> is valid XHTML, but you should use the above for compatibility reasons.

React anchor link delims not parsing data

I have a simple anchor / for loop:
<ul className="user-list">
{this.props.partymembers.map((user, i) => {
return (
<li key={i} className="membername">
{user.username}
</li>
)
})}
</ul>
But the link just shows up as /friends/add/{user.id} instead of /friends/add/141513531 am I missing something here? Thanks. Username shows fine, but not inside the ""
I managed to solve it by doing
<li key={i} className="membername">
{React.createElement('a', { href: '/friends/add'+user.id}, user.username)}
</li>
but that almost seems hacky, is there a better way to do it?
The whole attribute needs to be either a string or an expression. So something like this:
<a href={'/friends/add/' + user.id}>{user.username}</a>
If you're using babel to transpile ES6, you can use template strings:
<a href={`/friends/add/${user.id}`>{user.username}</a>

how to have no enclosing tags with React?

I want a component to return sibling tags instead of a single parent tag. For example render method of DefaultItems should return something that renders as <li/><li/> instead of say, <div><li/><li/></div>. But React needs enclosing tag when returning something.
Is there some null tag which does not insert into the final markup?
JSX:
<ul>
<DefaultItems/>
<OtherItems/>
<li>
Desired:
<ul>
<li>default 1</li>
<li>default 2</li>
<li>other 1</li>
<li>
The best I can do, notice the unwanted div around the li:
<ul>
<div>
<li>default 1</li>
<li>default 2</li>
</div>
<li>other 1</li>
<li>
I wish a "null tag" exists:
return <nulltag>
<li>default 1</li>
<li>default 2</li>
</nulltag>
A react components, render function must return a single element.
This 1 to 1 relationship makes components much easier to reason about.
What it means for us developers is that we have to divide our apps into components that follow this rule.
Rather than having a component that returns two li elements, you must return one. This is a good thing. It makes your components much more reusable.
A common pattern is to have one component that represents a list (of something), and a different component that represents the items in the list.
instead of:
...
<ul>
<ItemList items={list}/>
</ul>
...
you have:
...
<ItemList items={list}/>
...
you can still create a list of different items
...
makeList(items) {
return items.map(function (item) {
// return what ever component you want based on the item
});
},
render () {
return (
<ul>
{makeList(this.props.items)}
</ul>
);
},
...
You can work with arrays in React, but maybe you should reconsider the logic behind creating the list items.
Instead of having separate components for different data types, you can have a factory for creating arrays of list items inside the render method that passes the item data, f.ex something like this:
var i = 0
var listFactory = function(item) {
return <ListItem item={item} key={i++} />
}
var DefaultItems = defaultData.map(listFactory)
var OtherItems = otherData.map(listFactory)
<ul>
<DefaultItems />
<OtherItems />
</ul>
IMO, having a single component for a certain type (ListItem) is preferred over having separate components for different content or data.

Resources