I have this class function
class Fact extends React.Component {
render() {
return (
<img src="Logo.png"/>,
<center><p>FACT</p></center>,
<h1>Hello</h1>
)
}
}
export default Fact;
When running my localhost server, only "Hello" appears on the webpage. The logo doesn't appear, or the text message "FACT". Only "Hello" appears...How do I fix this?
Im trying to fit in 3 paragraphs as text to appear on my website, along with the logo. What's the best practice for this, rather then spam ?
You need to wrap the render output within a "root element", such as a <div> element to ensure that reactjs renders all the contents of the Fact component as you are expecting.
See the comments and code below, showing how to correct the error:
class Fact extends React.Component {
render() {
return (
<div> {/* Add <div> opening tag here */}
<img src="Logo.png"/>,
<center><p>FACT</p></center>,
<h1>Hello</h1>
</div> {/* Add </div> closing tag here */}
)
}
}
Note also that </h1> is missing the > in your question. This has been corrected in my answer
In React, if you're rendering multiple nodes (e.g. img, center, h1), you need to nest them under one parent node, e.g. <div>. That is, you can only return one top level node from your render function.
So:
class Fact extends React.Component {
render() {
return (
<React.Fragment>
<img src="Logo.png" /> ,
<center>
<p>FACT</p>
</center>
<h1>Hello</h1>
</React.Fragment>
);
}
}
Note that React.Fragment could also be something like a div.
Related
Here's a smaller example of what I'm trying to do, I don't know if it's possible to do something similar or I should use an entirely different method.
import {Design1, Design2} from './page-designs';
let designs = {
"page1":"Design1",
"page2":"Design2",
"page3":"Design1",
"page4":"Design2"
}
class DesignedPage extends React.Component {
let Design = designs[this.props.page]
render(){
return(
<div className="row flex-fill d-flex">
<div className="col-1"></div>
<Design /* This is the line that fails */
data = {this.props.data}
/>
</div>
</div>
)}
}
class Main extends React.Component {
render(){
return(
<DesignedPage
page = {this.props.openPage} /*this could be any of page1-4 depending on button a click*/
data = {this.props.data}
/>
)}
}
Ideally this would render the react elements Design1 or Design2 based on what props.page is passed, but instead it returns
"Warning: <Design1 /> is using incorrect casing. Use PascalCase for React components, or lowercase for HTML elements." and "The tag <Design1> is unrecognized in this browser. If you meant to render a React component, start its name with an uppercase letter."
I've thought of making a long if, elseif, elseif.. statement in DesignedPage (the actual code has many more than 2 designs), which I'm fairly confident would work, but looks very messy in comparison.
You can't render the component name by getting its name as a string. You need to map the string to the component iteself:
let designs = {
"page1":Design1,
"page2":Design2,
}
If you pass a string, react would think it's a HTML tag, hence it say'Design1' tag is unrecognised. Also, you could import the components and use them as values in the designs object in place of strings.
let designs = {
"page1":Design1,
"page2":Design2,
"page3":Design1,
"page4":Design2
}
make one function that return react component..
getComponent = ({data, pageName}) => {
if(pageName === "page1") return <Desig1 />;
if(pageName === "page2") return <Design2 />;
}
and call function from render of DesignedPage component
const {page, data} = this.props;
return(
<div className="row flex-fill d-flex">
<div className="col-1">
{getComponent(page, data)}
</div>
</div>
)
CalculateResults.js and ScoreBox.js are class components.
I send the result i wanna see in ScoreBox form CalculateResults like this:
CalculateResults.js
render(){
return(
<ScoreBox calculate={this.state.calculate} />
)
}
and i get this props in ScoreBox like this:
ScoreBox.js
render(){
return (
<div className="scoreBox d-flex">>
<div>
<p>score</p>
<h2>{this.props.calculate}</h2>
</div>
</div>
);
}
my problem is that it doesn't update scorebox, it renders another scorebox next to the previous one and shows the result there.
The whole story is like this: Scorebox component exists then When i click a button in UserMove.js a boolean called onlyChooseOne becomes true and i send some props to CalculateResults.js like this:
UserMove.js
render(){
return(
<div>
{
!onlyChooseOne
&&
<CalculateResult number={randomNumber} userChoice={userChoice} />
}
)
</div>
}
How should i fix it?
This question already has answers here:
How can I return multiple lines JSX in another return statement in React?
(8 answers)
Closed 4 years ago.
Learning a bit of React but it seems to me like there's a conditional rendering bug with React itself.
Suppose I have a Foo component like so:
foo.js
import React, { Component } from 'react';
class Foo extends Component {
render() {
const isLoggedIn = this.props.isLoggedIn;
return(
<div>
{ isLoggedIn ? (
<div>one</div><div>two</div>
) : (
<div>one</div><div>two</div><div>three</div>
)}
</div>
);
}
}
export default Foo;
and I use it like so:
app.js
import React, { Component } from 'react';
import Foo from './components/foo';
class App extends Component {
render() {
return (
<div>
<Foo isLoggedIn={false} />
</div>
);
}
}
export default App;
This produces the error:
Syntax error: Adjacent JSX elements must be wrapped in an enclosing tag
Please note the above Foo component, there is only a single parent div being returned not array. If it was an array, then yes I agree with the error.
The official example given in the React document's example is like this:
render() {
const isLoggedIn = this.state.isLoggedIn;
return (
<div>
{isLoggedIn ? (
<LogoutButton onClick={this.handleLogoutClick} />
) : (
<LoginButton onClick={this.handleLoginClick} />
)}
</div>
);
}
https://reactjs.org/docs/conditional-rendering.html
Does this look like a bug in React to anyone?
Update
Based on the answers and comments given here, the implied behaviour of React is ternary operators inside the render() function comes with it's own render calls behind the scenes, acting like a virtual component, which would mean an extra layer of <div> needs to be wrapped around the list of my child elements.
Emberjs Foo component
My confusion arise from the fact I have done some Emberjs development in the past and a component like this works as expected:
<h3>Foo component</h3>
{{#if isLoggedIn}}
<div>one</div><div>two</div>
{{else}}
<div>one</div><div>two</div><div>three</div>
{{/if}}
Thanks for the explanation from everyone nonetheless.
You are returning the 2 or 3 divs in the condition. Instead you should wrap them into on div and return.
Notice the wrapper div below.
{ isLoggedIn ? (
<div className='wrapper'><div>one</div><div>two</div><div>
) : (
</div className='wrapper'><div>one</div><div>two</div><div>three</div></div>
)}
Also note that there is small typo below
<div>one</div><div>two</div><div>three</div
You have a syntax error
<div>one</div><div>two</div><div>three</div
should be
<div>one</div><div>two</div><div>three</div>
Did you try adding ?
return(
<div>
{ isLoggedIn ? (
<Fragment><div>one</div><div>two</div><Fragment>
) : (
<Fragment><div>one</div><div>two</div><div>three</div><Fragment>
)}
</div>
);
Syntax error: Adjacent JSX elements must be wrapped in an enclosing tag?
you are returning multiple sibling JSX elements in an incorrect manner.
In Foo:
return(
<div>
{ isLoggedIn ? (
<div>one</div> //are siblings without
<div>two</div> //wrapping in container element.
) : (
<div>one</div> //are siblings without
<div>two</div> //wrapping in
<div>three</div>//container element.
)}
</div>
);
Right approach :
return (
<div>
{isLoggedIn
? (
<div> //add wrapper
/...
</div>
)
: (
<div> //add wrapper
//...
</div>
)}
</div>
);
Or
If you are using React16 then you can use React.Fragement as well:
e.g.
<React.Fragment>
<div>one</div>
<div>two</div>
</React.Fragment>
You need to wrap the element rendered in the condition
return(
<div>
{ isLoggedIn ? (
<div><div>one</div><div>two</div></div>
) : (
<div><div>one</div><div>two</div><div>three</div></div>
)}
</div>
);
Note the extra div around the nested conditional elements
I am trying to dynamically style a React element: In the nav bar, I would like to make the font color of the <div> displaying the current page to be different from the other <div>s representing other pages. I have passed into my <NavBar> component's props the params representing the current page.
From this information, I have figured out a way to achieve what I am trying to do: I store the <div>s representing the page links in an object and wrap the selected page in another <div> carrying a 'selected'class name.
However, I could envision scenarios where this solution would disrupt styling in place since it adds a wrapper element and classes within the wrapper element would take precedence over the 'selected' class.
Does anyone know a better way? I have posted my solution and the context below:
export default class NavBar extends React.Component {
constructor(props) {
super(props);
}
render() {
const pages = {
my_subscribed_docs:
<div className='nav__row2-item'>Documents I'm Subscribed To</div>,
my_created_docs:
<div className='nav__row2-item'>Documents I've Created</div>,
new_doc:
<div className='nav__row2-item'>
<div className="plus-icon">+</div>
<div className='nav__row2-text_left-of-icon'>New Document</div>
</div>,
};
const currentPage = this.props.path.slice(1);
pages[currentPage] =
<div className='nav__row2-item--selected'>{pages[currentPage]}</div>;
debugger;
return (
<nav>
<div className="nav__row1">
<div className="nav__logo">Worksheet Generator</div>
<div style={{cursor: 'pointer'}} onClick={this.props.logout}>
Logout
</div>
</div>
<div className="nav__row2" >
{ Object.values(pages).map( page => (
<div key={shortid.generate()}>{page}</div>)
) }
</div>
</nav>
);
}
}
If you want to dynamically add a class to your component, I recommend using classnames library. This is pretty much the way to do it when using external stylesheets.
(Sorry if too obvious and/or dup, couldn't find original one...)
How should I be able to comment out TodoTitle below? I tried with <!--...-->, //, /*...*/ with no luck.
class TodoApp extends React.Component {
render() {
return (
<div className="todo-app">
<TodoTitle />
</div>
);
}
}
You can comment {/* comment */} in JSX.
Can you not just use {/* stuff */} ?