Cannot connect page by address directly - javascript

I am making my own blog now and using react with react-router-dom.
When I type url except '/' in address bar directly, I get Cannot GET /url error in chrome.
But localhost:8000/ is working properly.
ex) localhost:8000/favorite ==> Cannot GET /favorite
And clicking header and redirect is working. Only typing in address bar is not working.
My codes structure simplified below.
index.js
const rootElement = document.getElementById('root');
ReactDOM.render(
<BrowserRouter>
<App />
</BrowserRouter>
,
rootElement);
App.js
class App extends React.Component {
render(){
return (
<div>
<Header/>
<Main></Main>
</div>
);
}
}
export default App;
Main.js
const Main = () => (
<main>
<Switch>
<Route exact path='/' component={HomeContainer}/>
<Route path='/post' component={Post}/>
<Route path='/favorite' component={Favorite}/>
<Route path='/setting' component={Setting}/>
</Switch>
</main>
)
export default Main
header.js
<div>
<Menu.Item><Link to='/'><Icon onClick={this.clickMenu} name='home' data- name='home' size="large"/></Link></Menu.Item>
<Menu.Item><Link to='/post'><Icon onClick={this.clickMenu} name='list'data-name='list' size="large"/></Link></Menu.Item>
<Menu.Item><Link to='/favorite'><Icon onClick={this.clickMenu} name='favorite' data-name='favorite' size="large"/></Link></Menu.Item>
<Menu.Item><Link to='/setting'><Icon onClick={this.clickMenu} name='settings' data-name='settings'size="large"/>/Link></Menu.Item>
</div>

Related

react-breadcrumbs throwing error when using with router

React Breadcrumbs is throwing some error when using with Router.
I am following this tutorial for implementation.
http://learnreact.robbestad.com/breadcrumbs
Below is the code:
var Breadcrumbs = require('react-breadcrumbs');
const Routes = () => (
<BrowserRouter>
<div>
<Header />
<MegaMenu />
{Breadcrumbs}
<Route exact path='/' name='HomePage' component={HomePage}/>
<Route path='/celebrity' name='Celebrities' component={Celebrities}/>
<Route path='/axios' name='Axios' component={Axios}/>
<Route path='/brands' name='Brands' component={Brands}/>
<Footer />
</div>
</BrowserRouter>
);
export default Routes;
Below is the error:
Objects are not valid as a React child (found: object with keys {Breadcrumb, Breadcrumbs}). If you meant to render a collection of children, use an array instead.
You shouldn't pass the reference directly but use it with React.createElement or in other words, in JSX land you should do just <Breadcrumbs />.
If you look carefully at the code from the link you posted (http://learnreact.robbestad.com/breadcrumbs):
var Breadcrumbs = require('react-breadcrumbs');
MyComponent = React.createClass({
render: function() {
return (
<div>
<Breadcrumbs />{/* You see it here, <Breadcrumbs /> not {Breadcrumbs} */}
</div>
);
}
});
It creates new React element and now let's check your code:
var Breadcrumbs = require('react-breadcrumbs');
const Routes = () => (
<BrowserRouter>
<div>
<Header />
<MegaMenu />
{Breadcrumbs}{/* <-------- Here is the issue */}
<Route exact path='/' name='HomePage' component={HomePage}/>
<Route path='/celebrity' name='Celebrities' component={Celebrities}/>
<Route path='/axios' name='Axios' component={Axios}/>
<Route path='/brands' name='Brands' component={Brands}/>
<Footer />
</div>
</BrowserRouter>
);
export default Routes;
If you replace {Bredcrumbs} with <Breadcrumbs />, it should just work:
var Breadcrumbs = require('react-breadcrumbs');
const Routes = () => (
<BrowserRouter>
<div>
<Header />
<MegaMenu />
<Breadcrumbs />
<Route exact path='/' name='HomePage' component={HomePage}/>
<Route path='/celebrity' name='Celebrities' component={Celebrities}/>
<Route path='/axios' name='Axios' component={Axios}/>
<Route path='/brands' name='Brands' component={Brands}/>
<Footer />
</div>
</BrowserRouter>
);
export default Routes;
You can read more about JSX in the official React documentation:
https://reactjs.org/docs/introducing-jsx.html
I have used this library https://www.npmjs.com/package/react-breadcrumbs-dynamic][1] to implement the breadcrumbs.
Created one route.js and imported the library
import { Breadcrumb as BootstrapBreadcrumb } from 'react-bootstrap'
import { Breadcrumbs, BreadcrumbsItem } from 'react-breadcrumbs-dynamic';
import CrumbItem from '../components/common/breadcrumb/CrumbItem';
Created the breadcrumbs container like this in route.js:
const Routes = () => (
<BrowserRouter>
<div>
<div className="breadcrumbs-container">
<BreadcrumbsItem glyph='home' to={base_path}>
Home Page
</BreadcrumbsItem>
<Breadcrumbs
hideIfEmpty={{ active: true }}
item={CrumbItem}
container={BootstrapBreadcrumb}
finalProps={{ active: true }}
duplicateProps={{ to: 'href' }}
/>
</div>
<Route exact path='/' component={HomePage} />
<Route path='/brands' component={Brands} />
<Footer />
</div>
</BrowserRouter>
);
Given breadcrumbs items in Another component brands.js
import { BreadcrumbsItem } from 'react-breadcrumbs-dynamic';
render() {
return (
<BreadcrumbsItem to={'/brands'}>
Brands
</BreadcrumbsItem>
)
}
Created link container separately
import { Breadcrumb } from 'react-bootstrap'
import { LinkContainer } from 'react-router-bootstrap'
const CrumbItem = ({to, ...props}) => (
<LinkContainer to={to}>
<Breadcrumb.Item {...props}>
</Breadcrumb.Item>
</LinkContainer>
)
export default CrumbItem
Note: Using bootstrap is optional

React router dom and layouts

I want to use layouts with my react-router-dom, at this moment i am doing that like this
const DefaultLayout = ({children, ...rest}) => {
return (
<div className={styles.wrapper}>
<Header/>
{children}
<Footer/>
</div>
)
};
const DefaultRoute = ({component: Component, ...rest}) => {
return (
<Route {...rest} render={matchProps => (
<DefaultLayout>
<Component {...matchProps} />
</DefaultLayout>
)}/>
)
};
render(
<Provider store={store}>
<HashRouter>
<Switch>
<DefaultRoute exact path="/" component={AdvertList}/>
<DefaultRoute exact path="/user" component={UserOptions}/>
<Route path="/login" children={Login}/>
<Route render={
() => (
<div>
Not found
</div>
)
}/>
</Switch>
</HashRouter>
</Provider>,
document.querySelector('#app')
);
it works okay, both UserOptions and AdvertList components are rendered inside DefaultLayout, and Login component does not, but in official documentation i didn't find solution like that, instead there is "nested routing" where you adding new nested routes in subclasses, like
if you need default layout u make it on route /, then if you need advert list with that layout, in layout component you defined route /adverts and adding link to it, and so on, each sub component uses layout of parent one.
But in my case there is already product list on route /, and i need to change that content to other products list regarding link pressed, not to add to parent layout, but to change it part. Here is my code,
const { BrowserRouter, Route, Switch, Link } = window.ReactRouterDOM;
const { Component } = window.React;
const About = () => ('About');
const MiscProducts = () => ('Misc products');
class AdvertsList extends Component {
render() {
return (
<div className="container">
<header>Header</header>
<main>
<nav>
<Link to="/miscProducts">Misc Products</Link> #
<Link to="/about">About</Link>
</nav>
<div className="content">
Main Products
</div>
</main>
<footer>Footer</footer>
<Route path="/miscProducts" component={MiscProducts} />
</div>
)
};
};
class App extends Component {
render() {
return (
<BrowserRouter>
<Switch>
<Route path="/" component={AdvertsList} />
<Route path="/about" component={About} />
<Route path="*" render={
() => (
<div>
Not found
</div>
)
}/>
</Switch>
</BrowserRouter>
);
}
}
ReactDOM.render(<App />, document.querySelector("#app"));
http://jsfiddle.net/gmcke2a4/6/ here main products loaded by default, and when i press misc products, misc products must be loaded instead of main one.
p.s. And why about doesn't work?
Login Fix
<Route path="/login" children={Login}/> this seems wrong because children component expects function which return nodes i think.Try <Route path="/login" children={() => (</Login />)}
Layout
But in my case there is already product list on route /, and i need to
change that content to other products list regarding link pressed, not
to add to parent layout
You can create component which renders specific products like this.
const MainProducts = () => 'Main Products'
const GummyBearsProducts = () => 'GummyBears'
const Products = props => (
<div className="products-container">
<Switch>
<Route path={`${props.location.pathname}`} component={MainProducts}/>
<Route path={`${props.location.pathname}/gummy-bears`} components={GummyBearProducts}/>
</Switch>
</div>
)
And then use it as follows.
class AdvertsList extends Component {
render() {
return (
<div className="container">
<header>Header</header>
<main>
<nav>
<Link to="/products">Products</Link> #
<Link to="/about">About</Link>
</nav>
<div className="content">
<Route path="/products" component={Products} />
</div>
</main>
<footer>Footer</footer>
</div>
)
};
};
React router is great in rendering specific components.I hope it answers your question.Cheers!
If you are using react-router-dom v6. Then follow the below procedure to configure react-router-dom,
App.jsx:
import './App.css';
import { BrowserRouter, Routes, Route } from 'react-router-dom'
import Home from './Components/Home'
import About from './Components/About'
import Layout from './Components/Layout'
function App() {
return (
<div className="App">
<BrowserRouter>
<Routes>
<Route path="/" element={<Layout />}>
<Route path="/" element={<Home />} />
<Route path="about" element={<About />} />
</Route>
</Routes>
</BrowserRouter>
</div>
);
}
export default App;
After configuring the react router in App.jsx. I am creating 3 components Home, About and Layout. Home and About are regular components and Layout component is to handle the Layout part in react-router-dom using Outlet.
Layout.jsx
import { Outlet, Link } from 'react-router-dom'
export default function Layout() {
return (
<>
<Link to="/">Home</Link>
<Link to="/about">About</Link>
<Outlet />
</>
)
}
Home.jsx
export default function Home() {
return (
<>
<p>This is Home</p>
</>
)
}
About.jsx
export default function About() {
return (
<>
<p>This is About Us</p>
</>
)
}

React Router - trigger file download

How to skip the react routing in case of file paths? It seems react router intercepts all links. Example below - the hardcoded link /1.pdf seems to trigger the router.
How do we trigger file downloads?
const Main = () => {
return (
<div>
<h1>React Router Playground</h1>
<Link to="/download">Download Area</Link>
</div>
);
};
const Download = () => {
return (
<div>
<h1>Download Area</h1>
Download
</div>
);
};
export default class App extends React.Component {
constructor(props) {
super(props);
this.state = {};
}
render() {
return (
<Router>
<div>
<Route exact path="/" component={Main} />
<Route path="/download" component={Download} />
</div>
</Router>
);
}
}
This is a rather simple example so the hardcoded link. These are dynamic and passed as props in the actual code.
The following code combined with a NoMatch component should work, reloading the URL if it's a valid resource.
<Router>
<div>
<Switch>
<Route exact path="/" component={Main} />
<Route exact path="/download" component={Download} />
<Route component={NoMatch} />
<Route onEnter={() => window.location.reload()} />
</Switch>
</div>
</Router>

react-router-dom on the server

I did find out that I can't use when I'm rendering my app on the server. I would like to wrap my App in specified router depending on the situation - BrowserRouter on the CLient side and StaticRouter on server side. My App looks like this:
imports......
class App extends Component {
constructor(props) {
super(props);
this.state = {
}
}
render() {
return (
<BrowserRouter>
<div>
<Menu />
<main>
<Switch>
<Route exact path="/about" component = {About} />
<Route exact path="/admin" component = {BooksForm} />
<Route exact path="/cart" component = {Cart} />
<Route exact path="/" component = {BookList} />
</Switch>
<Footer />
</main>
</div>
</BrowserRouter>
);
}
componentDidMount(){
this.props.getCart();
}
}
function mapDispatchToProps(dispatch) {
return bindActionCreators({
getCart
}, dispatch)
}
export default connect(null, mapDispatchToProps)(App);
I tried to move my BrowserRouter ou of this component so my index.js would look like this:
imports....
const renderApp = () => (
<Provider store={createStoreWithMiddleware(reducers)}>
<BrowserRouter>
<App/>
</BrowserRouter>
</Provider>
)
const root = document.getElementById('app')
render(renderApp(), root)
So I would get ability to wrap my app in different routers. The problem is when I moved BrowserRouter out of my App component it stopped working. Clicking on links just does not work anymore. The url is changing but my app isn't rendering differnet components. How can I move router out of this component?
On the server, you'll wrap your app similar to this:
const routerContext = {};
const appComponent = (
<Provider store={store}>
<StaticRouter location={req.url} context={routerContext}>
<App />
</StaticRouter>
</Provider>
);
Where you pass react-router the location (from the url) as well as a context object.
The client side is like your example:
<Provider store={createStoreWithMiddleware(reducers)}>
<BrowserRouter>
<App/>
</BrowserRouter>
</Provider>

React router v4 not rendering component

I'm new to React and trying to follow a tutorial on how to set up the router. However when I run the app, the component does not render, and the HTML just says react-empty.
index.js:
ReactDOM.render(
<Router>
<App />
</Router>,
document.getElementById('root')
);
App.js:
const App = () => (
<div>
<Main />
</div>
)
export default App;
Main.js:
const Main = () => (
<div>
<main>
<h1>MAIN</h1>
<Route exact path="/" component={Home}/>
</main>
</div>
)
export default Main;
Home.js:
class Home extends Component {
constructor() {
super()
console.log('home component');
}
render() {
return (
<div>
<h1 className="wat">waaaat</h1>
</div>
)
}
}
export default Home;
Also, I can see the Route in the React plugin for chrome like so: http://imgur.com/a/LXuwC
EDIT:
It works if i put:
<Switch>
<Route path="/" component={Home}/>
</Switch>
directly in App.js instead of the Main element.

Categories

Resources