I try to make a simple application with react, mongodb and nodejs. I reached the point where I need to route the application and for this I use "BrowserRouter" just as a test I separated some code into a separate component and tried to call it as a label in my base code in the App.js file, however I don't get an answer of it. It works fine while I have the code inside the App.js file but not outside it.
from the browser in the terminal it only tells me that there is an error in the code that separates and only that.
App.js
import React,{ Component } from 'react';
import { BrowserRouter, Switch, Route } from 'react-router-dom';
import Add from './Add';
class App extends Component{
render(){
return (
<BrowserRouter>
<div>
{/*Navigation*/}
<nav className="light-blue darken-4">
<div className="container">
<a className="brand-logo" href="/">Octopus</a>
</div>
</nav>
<Switch>
<Route path='/' component={Add}/>
</Switch>
</div>
</BrowserRouter>
)
}
}
Add.js
import React, { Component } from 'react';
class Add extends Component {
render() {
return (
<div className="container">
</div>
)
}
}
export default Add;
browser:
The above error occurred in the component:
in Add (created by App)
in div (created by App)
in Router (created by BrowserRouter)
in BrowserRouter (created by App)
in App
Related
I'm new to React and React Router and I am facing some trouble regarding the styling of the routes. So basically I have 2 routes: the main page and the admin page. All I want to do is to style the body so that in the admin page everything is centered. The problem is that each time i style the body, all the styling goes to the main page too. So how can I fix this issue?
You might me applying styling to you app.js file where BrowserRouter is implemented. Here is what you can do. Create your Home/Main page as:
import React from "react";
const Home = () => {
return <div style={{textAlign: "center" }}>Home</div>
}
export default Home;
Create your Admin page as:
import React from "react";
const Admin = () => {
return <div>Admin</div>
}
export default Admin;
And finally, Create your app.js file as:
import React from "react";
import { BrowserRouter, Switch, Route } from "react-router-dom";
import Admin from "./Admin";
import Admin from "./Home";
const App = () => {
return <BrowserRouter>
<Switch>
<Route path="/admin" component={Admin} />
<Route path="/" exact component={Home} />
</Switch>
</BrowserRouter>
}
export default App;
In this way, your only your Home page content is aligned centered. Hope this will help you.
I have a react.js site created using: https://facebook.github.io/create-react-app/docs/getting-started with the npx create-react-app my-app command. I got many pages in my app and when I open the rendered source code in google chrome after building the site. The problem is all pages are in one bundle.js including all text and HTML elements of all pages are in that file combined. Does someone know how to get the HTML rendered in the source code for all pages individually instead of having just a bundle.js for all pages content?
So the other pages can get indexed individually by google?
I hope someone knows how to get this working. If there is an npm plugin or an example site available please post the link. I really can't find a solution for weeks now, I just see a bundle.js in the exported HTML file that includes all text and images and HTML elements of all pages how can I have it rendered as html output instead of just all in one bundle.js for indexing purposes?
By the way: my app uses 'react-router-dom' I don't want to break, the routing of the pages but having the pages being indexable individually.
Below is a sample code
App.js
//App.js
import React, { Component } from 'react';
import {
BrowserRouter as Router,
Route,
Link
} from 'react-router-dom';
import Nav from './components/nav';
import Header from './components/header';
import Footer from './components/footer';
import home from './components/pages/home';
import about from './components/pages/about';
import contact from './components/pages/contact';
class App extends Component {
render() {
return (
<Router>
<div className="App">
<Nav/>
<Header/>
<Route exact path="/" component={home} />
<Route exact path="/about" component={about} />
<Route exact path="/contact" component={contact} />
<Footer/>
</div>
</Router>
);
}
}
export default App;
home.js
//home.js
import React, { Component } from 'react';
class home extends Component {
render() {
return (
<div className="container">
<p>content...</p>
</div>
);
}
}
export default home;
I'm new to React Router so if this has been asked before maybe someone could point me in the right direction! Basically I have a WordPress install that I'm pulling in my websites data from through the API.
I've created custom routes to query my pages and my posts by slug.
Using react router I was able to create a template called Page.js which changes dynamically using the code below.
However, now I'm trying to do the same exact thing with the blog posts but the app isn't using Blog.js its still defaulting back to Page.js
here's my App.js code...
import React from "react";
import { BrowserRouter as Router, Route } from "react-router-dom";
import Home from './pages/Home';
import Page from './pages/Page';
import Blog from './pages/Blog';
import Header from './components/Header';
import Footer from './components/Footer';
class App extends React.Component {
render() {
return (
<Router>
<div>
<Header/>
<Route exact path="/" component={Home} />
<Route path="/:slug" component={Page} />
<Route path="/blog/:slug" component={Blog} />
<Footer/>
</div>
</Router>
);
}
}
export default App;
More Details:
Page.js works by checking const { slug } = this.props.match.params; and then querying WordPress using that slug to pull in the data it needs. In componentDidUpdate i'm checking prevProps to see if the slug matches the previous slug, if not it fetching the new data.
This works great and I was hoping to do the same in the Blog.js as well.
However, if this isn't the best approach please advise another method.
Two things:
Use element: This will allow only one route to be used, no composing. (See this documentation)
Check the order of path statements: Use defined paths before :param, this avoids considering /blog/:slug as a /:slug parameter.
`
import { BrowserRouter as Router, Route, Switch } from "react-router-dom";
class App extends React.Component {
render() {
return (
<Router>
<div>
<Header/>
<Switch>
<Route exact path="/" component={Home} />
<Route path="/blog/:slug" component={Blog} />
<Route path="/:slug" component={Page} />
</Switch>
<Footer/>
</div>
</Router>
);
}
}
I think you're pretty close to the recommended implementation, just a few small tweaks should get you there.
First,
In your App.js file you're actually handling routing, without using the <Switch> component provided by React Router, replacing the <div> and </div> tags in your App.js file with <Switch> and </Switch> respectively should get this working for you. See below...
import React from "react";
import { BrowserRouter as Router, Route, Switch } from "react-router-dom"; //make sure you import it also!
import Home from './pages/Home';
import Page from './pages/Page';
import Blog from './pages/Blog';
import Header from './components/Header';
import Footer from './components/Footer';
class App extends React.Component {
render() {
return (
<Router>
<Switch> //Add this in
<Header />
<Route exact path="/" component={Home} />
<Route path="/blog/:slug" component={Blog} />
<Route path="/:slug" component={Page} />
<Footer />
</Switch> //Add this in
</Router>
);
}
}
export default App;
I would recommend going further though!
To make these components more understandable, you should refactor routing functionality into a routes.js file, and top-level App component logic/structure into the App.js file. See below...
In App.js:
This file is where you should handle your base application structure and logic. For example this file is where you'll import your <Header>, your <Footer>, and where the Route component will render.
import * as React from 'react'
import Header from './../Header/Header.jsx'
import Footer from './../Footer/Footer.jsx'
class App extends React.Component {
constructor(props) {
super(props)
this.state = {
// Handle your top-level application state here
}
}
// define your top-level application functions here
render() {
return (
<div>
<Header />
<main>
{this.props.children} //This where the Route components will render
</main>
<Footer />
</div>
)
}
}
export default App
In Routes.js:
This file is where you should import your App component, and then handle the routing statements.
import React from 'react'
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom'
import App from './components/App'
import Home from './pages/Home'
import Page from './pages/Page'
import Blog from './pages/Blog'
/* construct routes */
export default () => {
return (
<Router>
<App>
<Switch>
<Route path='/' exact component={Home} />
<Route path='/blog/:slug' component={Blog} />
<Route path='/:slug' component={Page} />
</Switch>
</App>
</Router>
)
}
If you structure your application this way, your routing logic and top-level application logic are separate, and in the end your files will be less cluttered as both Route files and top-level App files can get fairly dense.
Hope this helps! Let me know if I can explain anything further.
I'm new in this amazing site, I'm just having a problem in my react app.
this is the index.js I'm using react-router-dom in this page I just need to show this.state.show for who is in a home page, So in the login.js request I've created 'loginToken' with this code sessionStorage.setItem('loginToken', 'Value')
and now I'm making a verification for sessionStorage.getItem('loginToken') in index.js
Everything works fine but my problem is when I'm in a home page this text 'Welcome Back' doesn't appears automatically I need to refresh the home page to see it. I don't know why this happening.
Is it because I'm using componentWillMount?
I've tried to use componentDidMount I got same problem
import React, {Component} from 'react';
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';
import Login from './users/login';
import home from './news/index';
class App extends Component {
constructor(props){
super(props);
this.state = {
show: false
}
}
componentWillMount(){
if(sessionStorage.getItem('loginToken')){
this.setState({show: true});
}else{
this.setState({show: false});
}
}
render() {
return (
<div>
{this.state.show?
<div>welcome back</div>:null
}
<Router>
<Switch>
<Route path="/login" component={Login} />
<Route path="/home" component={home} />
</Switch>
</Router>
</div>
)
}
}
export default App;
Thank you so much for helping me.
This issue is componentWillMount only fires once when the app first is run since it is the most top level component in the tree.
You should look to pass a function as a prop into the Login component and call it in the login component to trigger a state change back in the parent component. You could follow an approach to doing so in this article.
The easiest approach would be to just move that welcome back text into a dashboard or home route this way it mounts and unmounts as you are expecting and you can use your current approach in that component.
I have set up a basic react app with hash navigation. Problem is when I click on any link to navigate between pages, I see that the hash in the url is changing properly, as well as I added a console.log in my layour's render to see if it's getting called and it is, with proper this.props.children values, however the page is not rendering anything. If I go to any route and refresh the page I see the correct components rendered, but if I navigate somewhere from there noting gets rendered until I refresh again.
import React from "react";
import ReactDOM from "react-dom";
import { IndexRoute, Router, Route, Link, hashHistory as history } from 'react-router';
class Layout extends React.Component {
render() {
console.log(this.props, document.location.hash);
return <div>
<div>
<span>LEYAUTI MLEAYTI {Math.random()}</span>
</div>
<div>
{this.props.children}
</div>
<div>
{this.props.params.project}
</div>
</div>
}
}
class CreateProject extends React.Component {
render() {
return <div>
<h1>Create PROEKT</h1>
</div>
}
}
class Projects extends React.Component {
render() {
return <div>
<h1>PROEKTI MROEKTI</h1>
<Link to="/projects/create">New project</Link>
</div>
}
}
ReactDOM.render(
<Router history={history}>
<Route path="/" component={Layout}>
<IndexRoute component={Projects}/>
<Route path="projects/create" component={CreateProject}/>
</Route>
</Router>,
document.getElementById('app-root'));
Here is a visual of what's happening in the console when I navigate on a couple routes, but the DOM remains unchanged
This may be an issue with hashHistory. Which react-router version are you using? With v4 and above, you need to use history like so -
import createHistory from 'history/createHashHistory'
const history = createHistory()
// pass history to the Router....
Your component didn't actually unmount/remount if you only update your hashtag in your url. The route however, is updated. So you can only see the component loads content for once when you refresh the page.
You will need to create state variables and update it in a routeChange handler callback and bind the updated state variable to your view by using setState. Then the component can get updated.
See this post for how to add the route change listener (https://github.com/ReactTraining/react-router/issues/3554)
Alright, so I got down to the bottom of it.
The problem was that I was including my client.min.js file before the default app.js file of laravel 5.4's default layout. For some reason it broke react in a very weird way. What I had to do is switch the order in which the two files were included.