My React component named 'Person' prints twice on the screen,once without props & once with props.
//App.js
import React, { Component } from 'react';
import './App.css';
import Person from './Person/Person'
class App extends Component {
render() {
return (
<div className="App">
<h1>Hello I am Arjun</h1>
<Person>But What's The Language?</Person>
<Person technology="React" syntax="JSX"/>
</div>
);
}
}
export default App;
//Person.js
import React from 'react'
const person = (props) => {
return (
<div>
<p>{props.children}</p>
<p>The technology used is {props.technology} & the syntax
is {props.syntax}</p>
</div>
)
};
export default person
And this is the output :
How can I solve this problem?
Other answers show you how you should do that and told the main reason. I will try to explain it a little bit more. You are rendering your component twice and you have three lines because of the structure of your component.
First render:
<Person>But What's The Language?</Person>
Here you are rendering the component with a child. Your child here is "But What's The Language?" string. You don't pass any other prop other then child. Your component shape is:
<p>{props.children}</p>
<p>The technology used is {props.technology} & the syntax is {props.syntax}</p>
First line is coming from the children prop. Second line is your paragraph with other props. So, in the first render you don't have those props, hence rendering as empty for technology and syntax.
Your second render:
<Person technology="React" syntax="JSX"/>
Here you don't have any child. It means no <Person>Child</Person> shape but just <Person /> For this render you have other props. Third line is coming from this render with technology and syntax props. Hence you don't have any children prop, first line is empty.
The issue is that you in fact render your component twice. You should have only one <Person /> Tag in your App component:
//App.js
import React, { Component } from 'react';
import './App.css';
import Person from './Person/Person'
class App extends Component {
render() {
return (
<div className="App">
<h1>Hello I am Arjun</h1>
<Person technology="React" syntax="JSX">But What's The Language?</Person>
</div>
);
}
}
export default App;
You are rendering your component twice, to obtain the desired output you could do something like this:
//App.js
import React, { Component } from 'react';
import './App.css';
import Person from './Person/Person'
class App extends Component {
render() {
return (
<div className="App">
<h1>Hello I am Arjun</h1>
<Person technology="React" syntax="JSX">
But What's The Language?
</Person>
</div>
);
}
}
export default App;
that way, your component renders its children "But What's The Language?", and receives the technology and syntax properties for the second line.
Related
Consider this first approach. It imports SomeMassiveModule in the Parent component and then passes it down to the Child components.
// Parent.js
import React from 'react'
import * as SomeMassiveModule from 'some-massive-module'
export default function Parent() {
return (
<Child SomeMassiveModule={SomeMassiveModule} />
<Child SomeMassiveModule={SomeMassiveModule} />
<Child SomeMassiveModule={SomeMassiveModule} />
)
}
// Child.js
import React from 'react'
export default function Child({ SomeMassiveModule }) {
return (
<div>
{SomeMassiveModule.SomeComponent}
</div>
)
}
Now, consider this second approach, which imports SomeMassiveModule in the Child component and then uses it.
// Parent.js
import React from 'react'
export default function Parent() {
return (
<Child />
<Child />
<Child />
)
}
// Child.js
import React from 'react'
import * as SomeMassiveModule from 'some-massive-module'
export default function Child() {
return (
<div>
{SomeMassiveModule.SomeComponent}
</div>
)
}
Is there a difference in performance between these two approaches? Does the bundling now happen three times in the second approach instead of just the once?
You can use the first approach when you want to pass different values in the props to the Child component. If it is going to be the constant (won't change in future) import option i.e 2nd approach seems better than the first one.
Im new to react and am currently trying to render some components.
My problem is that only the parent Component is being rendered.
I also have child Components but react doesnt seem to recognize them?
This is my index where I am importing my App component.
import ReactDom from 'react-dom';
import React from 'react';
import App from './app';
function BuildApp() {
return (
<App />
);
}
ReactDom.render(<BuildApp />, document.body);
Here is my App component.
import React from 'react';
import Container from './components/bootstrap-components/Container';
import TopInfo from './components/TopInfo/TopInfo';
export default function App() {
return (
<Container>
<TopInfo />
</Container>
);
}
The only thing my App Component renders is Container Component not the TopInfo.
If I remove the Container component and only have TopInfo, React will render TopInfo.
Refer to React children.
function Container(props) {
return (
<div>
{props.chilidren}
</div>
);
}
I'm trying to display a component in button click, What do I need to change in the syntax?
Anyone understand where the mistake is?
The functions works but not as I need to,
I have progressed since the previous question here display a different component with each button click
I really want to understand the right and the simple method
Thanks!
App.js
import React, {useState} from 'react';
import './App.css';
import Addroom from './components/Addroom.js'
import HomePage from './components/HomePage.js'
function App() {
const [flag, setFlag] = useState(false);
return (
<div className="App">
<h1>My Smart House</h1>
<button className="button1" onClick={()=>setFlag(!flag)}>Change Flag</button>
{flag.toString()}
<Addroom a={(!flag)}/>
<HomePage h={(flag)}/>
</div>
)
}
export default App;
HomePage.js
import React from 'react'
export default function HomePage(props) {
return (
<div>
<h2> HomePage {props.h}</h2>
</div>
)
}
Addroom.js
import React from 'react';
export default function Addroom(props) {
return (
<div>
<h2> Addroom {props.a}</h2>
</div>
)
}
With conditional operator condition ? exprIfTrue : exprIfFalse
{flag ? <Addroom /> : <HomePage /> }
If you don't need to use the flag inside components, skip passing as props
look at this sample
sample
I am trying to develop a webapp using reactjs and i have a issue. After more than 1 day of research, i don't understand how to do.
I want to use a component which are the main layout of my page adding other component to display in it.
In the component Base2, the child props contains another component.
import React from 'react';
import PropTypes from 'prop-types';
import { Link, NavLink } from 'react-router-dom';
const Base2 = (child) => (
<div>
<div className="top-bar">
<div className="top-bar-left">
<NavLink to="/">React App</NavLink>
</div>
<div className="top-bar-right">
<Link to="/login">Log in</Link>
</div>
</div>
<child/> // HERE the dynamic component
</div>
);
export default Base2;
The function calling it is :
const TestBase = ({props}) => {
return (<Base child={MyComponent}/>)
};
Moreover MyComponent can be a class declare following 2 methods:
import React from 'react';
import LoginForm from '../components/LoginForm.jsx';
class MyComponent extends React.Component{
constructor(props) {
super(props);
...
}
render() {
return (
<LoginForm
onSubmit={this.processForm}
onChange={this.changeUser}
errors={this.state.errors}
user={this.state.user}
/>
);
}
}
export default LoginPage;
Second method :
import React from 'react';
import { Card, CardTitle } from 'material-ui/Card';
const MyComponent = {
render() {
return (<Card className="container">
<CardTitle title="React Application" subtitle="Home page." />
</Card>);
}
};
export default MyComponent ;
During my tests, only the second method works. The lack of "instance" (something like that i guess) from the second method might be the issue?
How can I develop Base2 component to take these 2 types of component declaration?
Thanks in advance for your help
First pass the component like this:
<Base child={<MyComponent/>}/>
Then render it inside Base2 component by props.child, the way you wrote the Base2 component, child (just the argument name) will have the value of props not directly the component you are passing in props.
Write it like this:
const Base2 = (props) => (
<div>
<div className="top-bar">
<div className="top-bar-left">
<NavLink to="/">React App</NavLink>
</div>
<div className="top-bar-right">
<Link to="/login">Log in</Link>
</div>
</div>
{props.child} //here
</div>
);
In the second method seems to be a simple json containing a render method. To create component in your second method which seems to be wrote in es5 you have to use react.createClass({ render ... })
Seek on internet you will find a lot of es5 example
With the help of #Mayank Shukla i found the best way to do.
import React from 'react';
import PropTypes from 'prop-types';
import { Link, NavLink } from 'react-router-dom';
const Base2 = (props) => (
<div>
<div className="top-bar">
<div className="top-bar-left">
<NavLink to="/">React App</NavLink>
</div>
<div className="top-bar-right">
<Link to="/login">Log in</Link>
</div>
</div>
{props.child}
</div>
);
export default Base2;
The function calling it is :
const TestBase = (props) => {
return (<Base2 child={<MyComponent/>}/>)
};
First Method:
import React from 'react';
import LoginForm from '../components/LoginForm.jsx';
class MyComponent extends React.Component{
constructor(props) {
super(props);
...
}
render() {
return (
<LoginForm
onSubmit={this.processForm}
onChange={this.changeUser}
errors={this.state.errors}
user={this.state.user}
/>
);
}
}
export default LoginPage;
Second method :
import React from 'react';
import { Card, CardTitle } from 'material-ui/Card';
const MyComponent = (props) =>{
return (<Card className="container">
<CardTitle title="React Application" subtitle="Home page." />
</Card>);
};
export default MyComponent ;
I need to navigate to a route after an event is successful.
This seems to have changed since previous versions.
Previously we would do this:
import { browserHistory } from 'react-router';
...
handleClick(){
doSomething();
browserHistory.push('/some/path');
}
This example works in react-router and react-router-dom v4.0.0.
We have 3 components:
App.js - holds both Component 1 and Component 2
Component1.js - not wrapped in a Route and will always be rendered, but this will not have a reference of the "route props" - (history, location, match...)
Component2.js - rendered only if the route location match. Important thing to note that this component will be rendered with "route props"
To navigate programmatically, you can use react-router history object.
this.props.history.push('path');
This will work right off the bat for components rendered via Route, as these components will already have access to the route props (history). In our example this is Component2. However, for components that are not rendered via a Route (e.g. Component1), you would need to wrap it in withRouter to give you access to the history object.
App.js
import React, { Component } from 'react';
import { BrowserRouter, Route } from 'react-router-dom';
import Component1 from './Component1';
import Component2 from './Component2';
class App extends Component {
render() {
return (
<BrowserRouter>
<div>
<Component1 />
<Route path="/render1" render={() => <div>Rendered from Component1</div>} />
<Route path="/" component={Component2} />
<Route path="/render2" render={() => <div>Rendered from Component2</div>} />
</div>
</BrowserRouter>
)
}
}
export default App;
Component1.js
import React from 'react';
import { withRouter } from 'react-router';
class Component1 extends React.Component {
handleButtonClick() {
this.props.history.push('/render1');
}
render() {
return (
<div>
<h1>Component 1</h1>
<button onClick={this.handleButtonClick.bind(this)}>Component 1 Button</button>
</div>
);
}
}
const Component1WithRouter = withRouter(Component1);
export default Component1WithRouter;
For Component1, we wrapped it in withRouter, and then exported the returned wrapped object. Some gotcha, notice that in App.js, we still reference it as Component1 instead of Component1WithRouter
Component2.js
import React from 'react';
class Component2 extends React.Component {
handleButtonClick() {
this.props.history.push('/render2');
}
render() {
return (
<div>
<h1>Component 2</h1>
<button onClick={this.handleButtonClick.bind(this)}>Component 2 Button</button>
</div>
);
}
}
export default Component2;
For Component2, the history object is already available from this.props. You just need to invoke the push function.
If you are using "function components" and Hooks, instead of expecting props, use the useHistory() function instead:
import {useHistory} from 'react-router-dom';
export default function MyFunctionComponent() {
const history = useHistory();
const myEventHandler = () => {
// do stuff
history.push('/newpage');
};
// ...
}
Just render a redirect component:
import { Redirect } from 'react-router';
// ...
<Redirect to="/some/path" />
See docs here: https://reacttraining.com/react-router/core/api/Redirect
I really appreciate CodinCat's answer since he helped me resolve a different error, but I found a more correct solution:
In React Router 4.0 (I don't know about previous versions) the router passes a history object to the component (i.e.: this.props.history). You can push your url onto that array to redirect:
this.props.history.push('/dogs');
In my case though, I had two levels of components, the router called a component called LoginPage, and LoginPage called a component called Login. You'll only have the history object in the props of your child object if you pass it on:
<Router>
<Route path="/dogs" component={DogsPage}/>
<Route path="/login" component={LoginPage}/>
</Router>
const LoginPage = (props) => {
// Here I have access to props.history
return (
<div>
<Login history={props.history} />
</div>
)
}
const Login = (props) => {
function handleClick(){
// Now we can simply push our url onto the history and the browser will update
props.history.push('/dogs');
}
return (
<div>
<button onClick={handleClick}>Click to Navigate</button>
</div>
)
}
I know the example above is a bit contrived, since it would be easier in this case to just use a link, but I made the example this way to keep it concise. There are many reasons you may need to navigate this way. In my case, I was doing a graphQL request and wanted to navigate to the home page once a person had successfully logged in.