Can not add code comment inside GatsbyJS function - javascript

How I add code comment inside this Gatsby function. I search in web but not found yet.

Try:
export default () => {
// your comment here
return <div>
<NavBar />
{/* another comment here*/}
Hello People
<hr />
<Link to="/blog/">Blog Page</Link>
<div>
}
Note that I've self-closed the empty tags.
Adding the comment of Oliver:
To be precise, the syntax of HTML inside JS is called JSX, and it's a
syntactic extension to JavaScript typically employed by React (and
thus GatsbyJS) for cleaner code. To embed a JS expression in JSX you
need to use curly braces like this: {some expression}. Note that the
expression can be a comment, hence the {/*comment*/}

So The question was "How to add comment inside Gatsby JS function" That was a Tricky question. Actually I want to comment inside div elements. I found the solution. So t want to answer on my own.
Comment inside function but outside div element's #ferran-buireu is right but inside div element code comment be like;
{/* code comment */}

Related

How to open some child links in new tab in React

I have a page built with React (NextJS) and I am pulling some markup string content from Wordpress and inserting it into my JSX, like so:
...
<div className="wrapper">
<p
className="text-content"
dangerouslySetInnerHTML={{ __html: post.content.rendered }}
></p>
</div>
...
Now, the markup possibly contains links and I want to open all those links on new tab. So I tried:
...
<div className="wrapper">
<base target="_blank" />
<p
className="text-content"
dangerouslySetInnerHTML={{ __html: post.content.rendered }}
></p>
</div>
...
and all links in the markup are opened on new tab so, great. But the problem is that all other links in the page including those outside the div.wrapper element are opened in new tabs (since <base /> is scoped to the entire page) and I'll like to prevent this.
Since I can't use multiple <base /> on the same page, the other option I'm aware of is to loop through anchor tags of interest with document.querySelector(".wrapper a") and add the target attribute to all of them but, in React it's an anti-pattern to modify the DOM directly.
So I'm not sure how best to proceed. What do I do?
You can use DOMParser API to achieve that.
Here's a little snippet
const parser = new DOMParser();
const htmlText = `<div>Url link</div>`;
let content = parser.parseFromString(htmlText, "text/html");
const anchors = content.getElementsByTagName('a');
Array.from(anchors).forEach(a => {
a.setAttribute("target", "_blank");
})
console.log(content.body.innerHTML); // Here it is your new string
The code may need to be improved a bit, I've just typed this out of MDN example and I didn't have time to test it. Does this work?
Well first of all base element should only be inserted in html head element, and not inside the body html element, you could do that imperatively or using the react-helmet library - if you still need to use it.
dangerouslySetInnerHTML is in itself an imperative pice of code, but sometimes its the only possible solutions for a certain use cases, now regarding the links you could either do it using imperative code in a useEffect or componentDidMount, or you code use react-html-parser which will enable you to modify dom elements in a more declarative fashion - i say in a more declarative fashion because while its a react component in practice its still more imperative than its declarative in nature, but still better than custom code running in useEffect or componentDidMount

React: How to use same component twice in same page but loading one script tag for both just one time

I created a react component that I want to use twice(or more) inside my page, and I need to load a script tag for it inside the head of my page but just once! I mean even if I use the component twice or more in the page it should add the script tag just once in the head.
The Problem is that this script tag should be absolutely a part of the component and not statically inserted in the head of my page.
Can anyone help me to make the magic happens? Thanks a lot in advance!
You can give react-helmet a try for managing changes to your <head> from within React components.
In particular, you can check this example where rendering the same element four times only adds the script tag once.
For completeness, the relevant code from the example (although the interesting part is to see how it executes):
import { Helmet } from "react-helmet";
function ComponentWithHeader() {
return (
<div>
<div>Oh hi</div>
<Helmet>
<script src="fake-url.js" />
</Helmet>
</div>
);
}
const App = () => (
<div>
<ComponentWithHeader />
<ComponentWithHeader />
<ComponentWithHeader />
<ComponentWithHeader />
</div>
);
You can set the state of the parent component to keep in memory that the script is already added.
if (!this.state.scriptAdded) {
// Add script tag
this.setState({ scriptAdded: true });
}

trying to add br tag between the text in react

I am trying to add br tag between the text in react.
can you guys tell me how to add it.
I tried adding br tag... but if I add I get tag in the browser.
providng my code below.
can you guys tell me how to fix it.
let sportsDescription = '';
if(sportsInfo !== '' && !isSportsSetupActive) {
sportsDescription = 'testing <br /> testing';
}else if(isSportsSetupActive) {
sportsDescription = 'testing <br /> testing';
}
return (
<div id="main" className="section flex-container flex-full">
<section className="page-content flex-item">
<section className="gray-box">
<h2>Welcome to your dashboard{formatName}.</h2>
<p className="ft-intro ft-day1 ft-day2">{sportsDescription}</p>
</section>
</section>
</div>
);
From the ReactJS Docs...
In general, setting HTML from code is risky because it's easy to inadvertently expose your users to a cross-site scripting (XSS) attack. So, you can set HTML directly from React, but you have to type out dangerouslySetInnerHTML and pass an object with a __html key, to remind yourself that it's dangerous.
In your example, {sportsDescription} is interpreted as a string. React won't see anything inside that variable as a DOM element. That's why your <br/> only renders as a string.
Alternatively, you could do this (but it's generally a bad idea)...
<p
className="ft-intro ft-day1 ft-day2"
dangerouslySetInnerHTML={{__html:sportsDescription}}
/>
This way, React correctly recognized your intent to include HTML inside the string sportsDescription and renders the desired <br/> element.
Here's a quote from an article that goes into greater detail about Getting Started with ReactJS:
The React module has a createClass method that takes an object as its only parameter. We define only one key to start with: render. The value of render is a function that returns a virtual DOM element. One of the keys to React’s performance is its virtual DOM abstraction. Essentially, it’s a difference engine that calculates the difference between the existing DOM and the DOM that is to be rendered and only modifies the necessary elements and attributes. Inside the render function, you may have noticed that I included HTML markup. That’s JSX. It won’t pass validation as legal Javascript. Instead, it requires the Babel transpiler.
JSX only looks like HTML. JSX is just a syntactic extension of Javascript, where every JSX "tag" is actually a call of React.createElement function. SO you can't treat JSX as HTML, and therefore you can't simply use strings with HTML inside and expect them to act like DOM. What you should do is return other valid JSX:
let sportsDescription = '';
if(sportsInfo !== '' && !isSportsSetupActive) {
sportsDescription = (
<span>testing<br />testing</span>
);
} else if(isSportsSetupActive) {
sportsDescription = (
<span>testing<br />testing</span>
);
}
return (
<div id="main" className="section flex-container flex-full">
<section className="page-content flex-item">
<section className="gray-box">
<h2>Welcome to your dashboard{formatName}.</h2>
<p className="ft-intro ft-day1 ft-day2">{sportsDescription}</p>
</section>
</section>
</div>
);
Here,
<span>testing<br />testing</span>
is actually four calls of React.createElement, the first one is for span element, and three other are for its children: text node, br, text node.
Please read the documentation carefully.

How to correctly reference 'nested' tag with each={} in riotjs

I'm trying to work in the concept of a loading tag I can wrap other elements to give a consistent loading display when retrieving data async. Consider the following code:
This example relies on browserify (require) but shouldn't make a difference to
the question
<test>
<loading>
<ul>
1. = <li each={ items }>{ title }</li>
or
2. = <li each={ parent.items }>{ title }</li>
or
3. = <li each={ opt.data.items }>{ title }</li>
</ul>
</loading>
<script>
require('riot');
require('./loading.tag');
this.items = [
{ title: 'title 1'},
{ title: 'title 2'}
];
this.on('mount', function () {
riot.mount('loading', /* for 3 = */ {data: this.items});
})
</script>
</test>
As you can see, the tag is <test /> and contains a nested tag <loading /> which wraps the content <test /> displays. Problem is I'm unsure of the correct way to reference the items array (which would in the real world be pulled in via ajax). I tried options 1 & 2 but nothing would display. 3 works (passing the data as opts) but doesn't feel right.
It may have something to do with <yield /> which is how <loading /> is displaying its contents but I don't know why.
<loading>
<div><yield /></div>
</loading>
When I tried your above code 2 got the correct result. I have a few issues with your above code that may be causing you issues.
1) I've never used require inside of a tag. I doubt it works when requiring a tag file. The .tag extension does nothing. It's the type="riot/tag" that signals a script tag is not javascript but a special script that can be used by riot.
2) You've closed the tag </about> instead of </test>. I think your riot tag just won't compile under these circumstances.
3) I don't know what version of riot you're using, but in 2.3.12 if you mount the test tag then any children (in this case your "loadings") will automatically mount provided you have already loaded the .tag file. I think the problem is that you're calling mount on your "loading" tag twice, which may divorce them from their parent.
I think your issue is that the <loading> tag means nothing when <test> is mounted. You then require loading.tag, which then allows loading to be mounted. Try requiring <loading> before you mount test. I made a js fiddle with how I would do it. Hopefully this answers your question.
https://jsfiddle.net/cm09mtc5/

Is it possible to separate the javascript code from the tag file in Riot Js?

I would like to know if it is possible to do something like:
<todo>
<div class="greetings">Hello, world!</div>
<script src="/path/to/my/file.js"></script>
</todo>
The tag would keep the view (html) while the js code stays in a different file:
todo.tag (html/css)
todo.js
To give an alternative to the mixin solution, here is another way of splitting up your markup from your logic.
Take a look at this Plunker (a colleague of mine wrote this). The key part is the way you reference the tag function. <script>todoTag.call(this, this.opts);</script>. In this case, the todoTag is a global function. But nothing stops you from name spacing that function or use some form of module loading.
From the plunker:
todo.tag.html:
<todo>
<!-- your markup -->
<script>todoTag.call(this, this.opts);</script>
</todo>
todo.tag.js:
function todoTag(opts) {
// your logic
}
After looking into it i found that it is possible to separate the js from the tag file by using mixins. So, we would have something like:
<dropdown>
<select>...</select>
<!-- more html code here -->
this.mixin(Dropdown);
</dropdown>
The Dropdown instance will be in dropdown.js and the tag in dropdown.tag.
Hope this helps.
I've found another option to separate the js code from the tag by using a regular js constructor, like this:
<dropdown>
<!-- html code -->
<script>new Dropdown(this)</script>
</dropdown>
then we can just have
function Dropdown(tag) {
// constructor code
}
and
Dropdown.prototype = { ... }
as usual

Categories

Resources