React inline style not working with props - reactjs

I am trying to control the attributes left and right with props but keep coming up with an error
"Syntax error: this is a reserved word"
I've tried several different methods (and looked at various examples on StackO) to solve my answer and keep coming up with error. I've shortened my code to get to the meat and potatoes here.
I have this in my App.js, it works with Pulse.js until I try to pass props
class App extends Component {
render() {
return (
<div className="App">
<Nav />
<Content />
<Pulse top="-124" left="300" />
</div>
);
}
}
export default App;
And here is the code from Pulse.js
class Pulse extends React.Component {
render() {
return (
<Star style={{top: {this.props.top} + 'em'}}></Star>
);
}
}
export default Pulse;
when I enter "this.props.top" as my style, I get my error. I've tried various methods to fix this and continue coming up with errors. Thanks for your help!

<Star style={{top: {this.props.top} + 'em'}}></Star>
Remove the syntactically invalid wrapping {} around this.props.top
<Star style={{top: this.props.top + 'em'}}></Star>
A bit more explanation:
JSX is a "DSL", a domain specific language. It's not Javascript. In JSX, you can put vanilla Javascript expressions inside of curly braces in some places, like
<Star style={...vanilla javascript expression...} />
Once you're inside the curly braces, there's no need for additional curly braces to read variables. You can reference this.props.top without wrapping it in more curly braces.
When you use this syntax: {this.props.top} the compiler gets confused, thinking you're trying to build a javascript object like {a: 'b'} but instead of a, you're trying to use the word this, which is a reserved word in Javascript. The compiler thinks you're trying to do something like {this: this} which is invalid, because the bare word this is a reserved word.

Related

React - is there a way to return JSX which contains braces? [duplicate]

I'm new to React and I'm trying to figure out the purpose/use of <MyComponent></MyComponent> vs <MyComponent />. I can't seem to find information on anything except self-closing tags.
I've created a basic tab scroller as a JSFiddle using the self-closing <MyComponent /> and subsequent props, and I'm wondering if there's a better way to write in React than what I've done.
class TabScroller extends React.Component {
render() {
return (
<div className="tabScroller">
<div className="NavList">
<TabNav handleClick={this.handleNavClick} />
<TabList
tabs={this.state.tabs}
activeTab={this.state.activeTab}
scrollPosition={this.state.scrollPosition}
handleClick={this.handleTabClick}
/>
</div>
<TabContent content={this.state.tabs[this.state.activeTab].content} />
</div>
);
}
}
// ========================================
ReactDOM.render(
<TabScroller />,
document.getElementById('root')
);
In React's JSX, you only need to write <MyComponent></MyComponent> when the component has child components, like this:
<MyComponent>
<Child />
<Child />
<Child />
</MyComponent>
If there is nothing between <MyComponent> and </MyComponent>, then you can write it either <MyComponent/> or <MyComponent></MyComponent> (but <MyComponent/> is generally preferred). Details in Introducing JSX.
Just as a side note, you'd access those children in your component via the special props.children property. More in JSX in Depth: Children in JSX.
Note that this is very much not like HTML or XHTML. It's its own (similar) thing with different rules. For instance, in HTML, <div/> is exactly the same thing as <div>: A start tag, for which you must eventually have an end tag. Not so JSX (or XHTML). The rules for HTML are that void elements (elements that never have markup content, such as br or img) can be written with or without / before > and they never get an ending tag, but non-void elements (like div) must always have an ending tag (</div>), they cannot be self-closing. In JSX (and XHTML), they can be.
The purpose of self-closing tags is simply the fact that it is more compact. This is especially useful when said component doesn't have any children that you typically wrap around a parent.
So usually for leaf components (i.e compoents that do not have any children), you use the self-closing syntax. Like: <Component />. And even if it has props, you can do: <Component foo="bar" />.
However, remember that children is a prop, so you could technically do:
<Component children={<span>foo</span>} />
but I find it less readable and advise against it (read disclaimer below).
To summarize, these are equivalent:
<Component /> = <Component></Component>
<Component foo="bar" /> = <Component foo="bar"></Component>
<Component children={<span>foo</span>}></Component> =
<Component><span>foo</span></Component>
You can use whichever approach you prefer. Though praxis is to use the short-hand version when there are no children.
Disclaimer: While defining childen prop by its object key value will technically work, doing so is strongly discouraged as it disrupts the API as it is meant to be used. Use this version only if confident in what you are doing.

Material-ui Google Maps Place Component Doesn't Keep Text When Placed In My Custom Function

React/NextJS/Material-UI newbie issue, hoping someone can share some insight. I'm using Material-ui Google Maps Place component (https://material-ui.com/components/autocomplete/#google-maps-place) out-of-the-box, nothing custom. But for some reason it doesn't work when wrapped inside of my custom function HideOnScroll, as shown below, which just hides my header onScroll. It will render and fetch Google places but it will only accept one character and then immediately goes back to null/original state upon typing second character. But it works perfectly when outside of this HideOnScroll function. Any idea on what I'm doing wrong? My guess is it's a state issue but I'm not clear on how to resolve it.
My custom function:
const HideOnScroll = (props) => {
const { children } = props;
const trigger = useScrollTrigger();
return (
<Slide appear={false} direction="down" in={!trigger}>
{children}
</Slide>
);
}
This works:
return (
<header>
<AppBar className={header}>
<div className={topTrim}></div>
{mobileView ? displayMobile() : displayDesktop()}
<div>{GoogleMaps()}</div>
</AppBar>
</header>
);
This does not work:
return (
<header>
<HideOnScroll {...props}>
<AppBar className={header}>
<div className={topTrim}></div>
{mobileView ? displayMobile() : displayDesktop()}
<div>{GoogleMaps()}</div>
</AppBar>
</HideOnScroll>
</header>
);
FYI, the displayDesktop() function is below and I'm currently just trying to get this to work on desktop. I have also tried adding {GoogleMaps()} to this function as well but still experienced the same problem.
const displayDesktop = () => {
return (
<Toolbar className={toolbar}>
<div className={toolBarTop}>{logo()}</div>
</Toolbar>
);
};
GoogleMaps is a React functional component, and it must not be treated as a normal function. Since it is called like a normal function in JS, it no longer retains its properties as a component and loses its state and lifecycle methods. (This means your hooks will stop working too)
To fix this, consider calling the functional component using the angular bracket syntax, i.e. <GoogleMaps/>.
Also, by convention, the names of all user-defined components should start with a capital letter to distinguish them from regular/pre-defined components.
This article deals with this exact issue with details.

Variable with the exact name of the component in the scope

Just started learning React from zero, regarding components ( when we define them with Uppercase letter), the tutorial is saying
there must be a variable in the scope with that exact name.
I don't understand that and I don't SEE it from the examples of this tutorial.
Here he has:
function MyComponent() {
var data = "world";
return (
<div>
<h1>Hello</h1>
<h2>{data}</h2>
</div>
);
}
Capital Letter. Got it. OK. then we can use it like:
<div>
<div> Greetings </div>
<MyComponent />
</div>
So from that example I can't see and understand what is he talking about. Can someone explain it?
it's talking about what happens behind the scenes.
Your react code you'll be transpiled by babel, and it'll call React.createElelement function. that's why you need to import React.
Remember MyComponent is a function variable after all. React.createElelement calls that function behind the scenes. To be able to call MyComponent (it's when you do <MyComponent />), MyComponent must exists in the first place in the scope where you do <MyComponent />. Meaning, either you have created MyComponent in that scope, or you've imported that variable (as import MyComponent from './<path>/MyComponent') to that scope.

How to enter comments in React: What is the equivalent of html <!-- -->?

In html to create a comment we use:
<!-- Write your comments here -->
What is its equivalent in React while using React components in the return section of a react component? Sometimes I just want to place some comments like
<!-- <MyComponent .... /> -->
but I can not do it in this way
You cannot do regular HTML comments in jsx, the closest you can get is JS-style comments -
{/* This is a comment */}
You have to wrap in curly braces, and then block comment: {/* <div /> */}
As mentioned in comments. You can write comments in React like below
{ /* <MyComponent .... /> */ }
Can add comment in React code on the one line
// comment
Comment in other place than is html tags for more rows
/* comments*/
But comment can add and to return part of class with {/* coments*/}. This away can get possibility write comments to more lines, like is can write comments to Java, C++, Javascript
write comments as you might do in HTML and XML with <!-- --> syntax.
will throw Unexpected token error.
To write comments in JSX, you need to use JavaScript’s forward-slash and asterisk syntax, enclosed inside a curly brace {/* comment here */}.
Here’s the example:
export default function App() {
return (
<div>
<h1>Commenting in React and JSX~ </h1>
{/* <p>My name is Bob</p> */}
<p>Nice to meet you!</p>
</div>
);
}
Ref

Why are Fragments in React 16 better than container divs?

In React 16.2, improved support for Fragments has been added. More information can be found on React's blog post here.
We are all familiar with the following code:
render() {
return (
// Extraneous div element :(
<div>
Some text.
<h2>A heading</h2>
More text.
<h2>Another heading</h2>
Even more text.
</div>
);
}
Yes, we need a container div, but it's not that big of a deal.
In React 16.2, we can do this to avoid the surrounding container div:
render() {
return (
<Fragment>
Some text.
<h2>A heading</h2>
More text.
<h2>Another heading</h2>
Even more text.
</Fragment>
);
}
In either case, we still need need a container element surround the inner elements.
My question is, why is using a Fragment preferable? Does it help with performance? If so, why? Would love some insight.
It’s a tiny bit faster and has less memory usage (no need to create an extra DOM node). This only has a real benefit on very large and/or deep trees, but application performance often suffers from death by a thousand cuts. This is one cut less.
Some CSS mechanisms like Flexbox and CSS Grid have a special parent-child relationship, and adding divs in the middle makes it hard to keep the desired layout while extracting logical components.
The DOM inspector is less cluttered. :-)
You can find the descriptions of some other use cases in this React issue: Add fragment API to allow returning multiple components from render
Adding to all answers above there is one more advantage: code readability, Fragment component supports a syntactic sugar form, <>. Thus the code in your question can be written more easily as:
render() {
return (
<>
Some text.
<h2>A heading</h2>
More text.
<h2>Another heading</h2>
Even more text.
</>
);
}
According to docs,
In React, this desugars to a <React.Fragment/> element, as in the example from the previous section. (Non-React frameworks that use JSX may compile to something different.)
Clutter-free, right ?
Note that you still need to use <Fragment> syntax if you need to provide key to the fragment.
Added features not possible before with JSX
Better semantic jsx markup. Wrapper elements are used when needed not because they are forced to.
Less overall dom markup (increased render performance and less memory overhead)
It as simple as when you don't need a wrapper element you aren't forced to use one. Having less elements is great but I think the biggest benefit is being able to render elements in jsx that weren't previously possible and adding better semantic meaning to wrapper elements because they are optional now.
This wasn't possible before:
<select>
{this.renderOptions()}
</select>
Glancing at the following in React 15 you can't tell if the wrapper element is needed or not:
<span>
<h1>Hello</h1>
{this.getContent()}
</span>
As per the reactjs.org docs most important needs of <Fragment> </Fragment> instead of div's are to avoid breaking HTML semantics. When we use div's instead of <Fragment> </Fragment> we break the HTML semantics.
To know more about html semantics. please click
and also there are cases where if you use div's instead of Fragments it will be invalid html, for example look at this code:
class Columns extends React.Component {
render() {
return (
<div>
<td>Hello</td>
<td>World</td>
</div>
);
}
}
<table>
<tr>
<div>
<td>Hello</td>
<td>World</td>
</div>
</tr>
</table>
Fragments solve this problem.
When working with React, there are cases where you will need to render multiple elements or return a group of related items. Here’s an example:
function App() {
return (
<h1>Hello React!</h1>
<h1>Hello React Again!</h1>
);
}
If you try to run your app with the code above, you will run into an error stating that Adjacent JSX elements must be wrapped in an enclosing tag. This implies that you need to wrap both elements within a parent div.
function App() {
return (
<div>
<h1>Hello React!</h1>
<h1>Hello React Again!</h1>
</div>
);
}
Doing this will fix the error, but it comes with a degree of risk. You are adding an extra node to the DOM, which is not necessary. In a case like this, where the above is a child component that will be enclosed within a parent component, this becomes a problem.
function Table() {
return (
<table>
<td>This is a Table Component</td>
<Columns />
</table>
);
}
function Columns() {
return (
<div>
<td>Hello React!</td>
<td>Hello React Again!</td>
</div>
);
}
The resulting HTML for the Table component will be invalid because of the additional div that was added.
function Table() {
return (
<table>
<td>This is a Table Component</td>
<div>
<td>Hello React!</td>
<td>Hello React Again!</td>
</div>
</table>
);
}
Let’s take a look at a better way of solving this by using React Fragment, which will not add any additional node to the DOM. The syntax looks like this:
function Columns() {
return (
<React.Fragment>
<td>Hello React!</td>
<td>Hello React Again!</td>
</React.Fragment>
);
}
You can also use the short syntax <></> for declaring a Fragment.
function Columns() {
return (
<>
<td>Hello React!</td>
<td>Hello React Again!</td>
</>
);
}
Using <React.Fragment>...</React.Fragment>, we can add a parent tag to our JSX elements without adding an extra node to the DOM.
you can replace the extra div tags with React.Fragment
writing React.Fragment every time is too long for you. React.Fragment has a shorthand syntax that you can use. It is <>...</>.
When you want to group components but don't want a div tag HTML in the generated HTML, you can use fragment. The generated HTML for <> <p> Hello </p> </> is just this: <p> Hello </p>
If we'd have used div container, the <div>…</div> will be generated too!

Resources