I am very new to react. I tried to use react-router. But no matter how I change the code, it always give me the warning.
Warning: No route matches path "/". Make sure you have somewhere in your routes
After googling for few hours, still have no idea what is wrong. Can anyone give me some hint? Thank you
In my app.js
Router.run(routes, Router.HistoryLocation, function(Handler, routerState) {
var params = routerState.params;
React.render(
<Handler params={params}/>,
document.getElementById('react-app')
)
});
In my route.js
var routes = (
<Route name="root" path="/" handler={App}>
<DefaultRoute handler={Home} />
<Route name="commitments" handler={CommitmentList} />
<Route name="commitment" handler={Commitment} />
</Route>
);
I am also use express and tring to do server-side rendering,
module.exports = {
index: function(req, res) {
var path = req.url;
Router.run(routes, req.url, function(Handler) {
var handler = React.createElement(Handler);
var markup = React.renderToStaticMarkup(handler);
res.render('home', {
markup: markup // Pass rendered react markup
});
});
}
}
Your App handler is missing in app.js
Related
Am using react router v6 and i would like to use the new loader to load the data before the component loads. So i have the following
In my index.js
const router = createBrowserRouter(
createRoutesFromElements(
<Route path="*"
loader={async ({ params }) => {
console.log("index loader log"); //this logs
return true;
}}
element={<App />}
> </Route>
)
);
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<RouterProvider router={router} />
);
in my app component i have nested routes like
const App = () => {
return (
<>
<Routes>
<Route path="auth/*" element={<AuthLayout/>}/>
<Route path="about"
loader={async ({ params }) => {
console.log("about child loader log"); //this doesnt log
return true;
}}
element={<AboutPage/>}/>
</Routes>
<h1>Testing app</h1>
</>
);
}
On the app component the loader on the Route path="about" does not console.log when i visit the about route but the component is rendered. What am i missing for the loader to work on the child route.
Based on some basic testing it seems that in order for the new RRDv6.4 data APIs to work you need to specify the complete routing configuration in the createBrowserRouter function.
There does however appear to already be an issue filed with #remix-run/react-router for this behavior as a reported bug, so you may want to follow it if it ever addressed/resolved. (I suspect it was you since the name is "geoffrey" and the timing is coincidentally about an hour ago around the same time as this post)
This above issue has since been closed with comment:
Descendant <Routes> trees do not participate in data loading
(https://reactrouter.com/en/main/components/routes) since they cannot
be known ahead of render-time. You'll need to lift your descendant
route definitions up into the routes you pass to createBrowserRouter.
The relevant information regarding the descendent routes and the new Data API can be found in the Routes documentation in a note.
Note:
If you're using a data router like createBrowserRouter it is
uncommon to use this component as it does not participate in data
loading.
Hoist the entire route declaration to the parent creating the data router. The following does work with the loader function for the "/about" route and About component.
const router = createBrowserRouter(
createRoutesFromElements(
<Route
path="*"
loader={({ params }) => {
console.log("index loader log");
return "This is the App";
}}
element={<App />}
>
<Route path="auth/*" element={<AuthLayout />} />
<Route
path="about"
loader={({ params }) => {
console.log("about child loader log");
return "this is the about page";
}}
element={<AboutPage />}
/>
</Route>
)
);
The App component should render an Outlet for the nested routes to render their content into.
import { Outlet } from 'react-router-dom';
const App = () => {
return (
<>
<h1>Testing app</h1>
<Outlet />
</>
);
};
I'm stuck with a problem in my project. I'm trying to show a component and work with the this.props.match.params, but no matter what I do I get undefined.
Routes:
const App = () => (
<BrowserRouter>
<Fragment>
<Header/>
<main>
<Switch>
<Route path="/show/:id" component={Show}/>
<Route path="/" component={Home}/>
</Switch>
</main>
</Fragment>
</BrowserRouter>
);
export default App;
then I have a handler on my home route:
async handleSubmit(searchId) {
const id = await DwellingService.findSiocId(searchId);
if (id) {
this.props.history.push(`/show/${id}`);
}
}
and finally on my show component
componentDidMount() {
console.log(this.props.match.params)
const {id} = this.props.match.params;
if (id) {
this.props.requestFindDwelling(id);
}
}
So I have been researching and I think is not a react router problem, first when I try to access the routes by typing them I was getting unexpected > on my bundle.js which was solved adding <base href="/" /> on the index.html.
Now my component is rendering ok by the console.log of the show component is giving me this:
isExact:false
params:{}
path:"/show"
url:"/show"
When I started the project to be able to use browserhistory and not getting error by refreshing the page I had to add this to my index file:
app.get('/*', function(req, res) {
res.sendFile(path.join(__dirname, './public/index.html'), function(err) {
if (err) {
res.status(500).send(err);
}
});
});
For the kind of error I get I'm supposing the route is not being found and is redirecting me to /show.
<Switch>
<Route path="/show/:id" component={Show}/>
<Route path="/" component={Home}/>
</Switch>
This will never render Home as Switch renders first thing that matches and / will match always the first route. Not sure if this will fix the problem but try and let me know:
<Switch>
<Route exact path="/" component={Home}/> // exact is important
<Route path="/show/:id" component={Show}/>
</Switch>
Using React-Router in ES5, I have the below code
var React = require('react');
var Render = require('react-dom').render;
var Router = require('react-router').Router;
var Route = require('react-router').Route;
var hashHistory = Router.hashHistory;
var browserHistory = Router.browserHistory;
var About = require('./components/about/aboutPage');
var routes = (
<Router>
<Route path="/" handler={App}>
<Route path="about" handler={About}/>
</Route>
</Router>
);
module.exports = routes;
This is rendered in {main.j} as
var ReactDOM = require('react-dom');
var Router = require('react-router').Router;
var routes = require('./routes');
ReactDOM.render(<Router>{routes}</Router>, document.getElementById('app'));
However, in the console, am getting this warning and nothing loads up:
bundle.js:1845 Warning: [react-router] `Router` no longer defaults the history prop to hash history. Please use the `hashHistory` singleton instead
I have clearly passed {hashHistory} in the code above, but still it keeps on complaining.
Any hints on what could be going wrong?
Thanks
No you didn't.You have just defined it and not used it. You have to pass history={hashHistory} in the router Tag.
var React = require('react');
var Render = require('react-dom').render;
var Router = require('react-router').Router;
var Route = require('react-router').Route;
var hashHistory = Router.hashHistory;
var browserHistory = Router.browserHistory;
var About = require('./components/about/aboutPage');
var routes = (
<Router history={hashHistory}>
<Route path="/" handler={App}>
<Route path="about" handler={About}/>
</Route>
</Router>
);
module.exports = routes;
P.S. react-router 2.8.0 requires react v15.3.0 and above. Visit the
following link.
https://www.versioneye.com/nodejs/react-router/2.8.0
If you dont have this, I would suggest you use react-router v2.0.0 or update you react to the required version.
Found the reason - It was an issue with my rendering code
ReactDOM.render(<Router>{routes}</Router>, document.getElementById('app'));
as {routes} already contained {}, there was no need to specify it again whilst rendering. Because of this, ofcourse, {history} prop was missing in the render code. So, I just changed the render code to:
ReactDOM.render(routes, document.getElementById('app'));
and it works perfectly fine!
Thanks
React-router is off to a really bad start... What seems basic doesn't work. Using react-router 2.0.0 my Link component updates the URL to be /about, but my page doesn't render the About component after that...
Entry point js
var React = require('react');
var ReactDOM = require('react-dom');
var Router = require('react-router').Router;
var Route = require('react-router').Route;
var hashHistory = require('react-router').hashHistory;
var App = require('./components/App.react');
var About = require('./components/About');
ReactDOM.render(
<Router history={hashHistory} >
<Route path="/" component={App}>
<Route path="about" component={About} />
</Route>
</Router>,
document.getElementById('app')
);
App.js
'use strict';
var React = require('react');
var Link = require('react-router').Link;
var Header = require('./Header');
var UserPanel = require('./UserPanel');
var ModelPanel = require('./ModelPanel.react');
var EventPanel = require('./event/EventPanel');
var VisPanel = require('./vis/VisPanel');
var LoginForm = require('./LoginForm');
var AppStore = require('../stores/AppStore');
var AppStates = require('../constants/AppStates');
var App = React.createClass({
[... code omitted ...]
render: function() {
var viewStateUi = getViewStateUi(this.state.appState);
return (
<div>
<Header />
<Link to="/about">About</Link>
{viewStateUi}
</div>
);
}
});
For some reason, the <Link>s were not working for me with the configuration below.
// index.js
ReactDOM.render(
<Provider store={store}>
<BrowserRouter >
<App />
</BrowserRouter>
</Provider>,
document.getElementById('root')
);
// App.js
return (
<div className="App">
<Route exact={true} path="/:lang" component={Home} />
<Route exact={true} path="/" render={() => <Redirect to={{ pathname: 'pt' }} />} />
<Route path="/:lang/play" component={Play} />} />
<Route path="/:lang/end" component={End} />
</div >
);
The Home component had the Link, but Links on the App would do the same. Every time I clicked it, it would only change the url, but the views would stay the same.
I was able to put it working when I added withRouter to the App.js
export default withRouter(connect(mapStateToProps, { f, g })(App));
I still don't understand what happened. Maybe it's related with redux or there is some detail I'm missing.
Since the 'About' route is a child of the 'App' route, you need to either add this.props.children to your App component:
var App = React.createClass({
render: function() {
var viewStateUi = getViewStateUi(this.state.appState);
return (
<div>
<Header />
<Link href="/about">About</Link>
{viewStateUi}
{this.props.children}
</div>
);
}
});
or separate your routes:
ReactDOM.render(
<Router history={hashHistory} >
<Route path="/" component={App} />
<Route path="/about" component={About} />
</Router>,
document.getElementById('app')
);
None of the solutions worked for me, including adding withRouter to my Component. I was experiencing the same issue where the browser's address bar updates the URL but the component doesn't render. During the debugging of my issue, I realize I have to present the context of my problem because it is a bit different from what the OP had.
The route I was trying to get to work was a dynamic route that takes an arbitrary parameter, e.g.
<Route path={`/hr/employees/:id`} component={EmployeePage} />
The component this route uses is "self-referential", meaning that within the component or its children components, they have a Link component that directs to /hr/employees/:id, but with a different id. So let's say if I was at /hr/employees/3 and on the page, there was a link to /hr/employees/4, e.g. <Link to='/hr/employees/4'>, I would get this problem where the component didn't re-render.
To solve this problem, I simply modified the componentDidUpdate method of my EmployeePage component:
componentDidUpdate(prevProps) {
if (this.props.match.params.id !== prevProps.match.params.id) {
// fetch data
}
}
If you're using functional components, use useEffect:
const EmployeePage = props => {
const {id} = props.match.params
useEffect(() => {
// fetch data
}, [id])
}
I've got code similar to following:
var browserHistory = ReactRouter.browserHistory;
var Router = ReactRouter.Router;
var Route = ReactRouter.Route;
var Link = ReactRouter.Link;
class App extends React.Component {
render() {
return (
<div>
<h1>Here is content:</h1>
{this.props.children}
<Link to="/Welcome">Welcome</Link> |
<Link to="/Login">Login</Link>
REFERENCE LINK
</div>
);
}
}
class Welcome extends React.Component {
render() {
return (
<div>
<h1>No hejaaaa - welcome</h1>
</div>
);
}
}
class Login extends React.Component {
render() {
return (
<div>
<h1>No hejaaaa - Login</h1>
</div>
);
}
}
const Routes = (
<Router history={browserHistory}>
<Route path="/" component={App}>
<Route path="Welcome" component={Welcome}/>
<Route path="Login" component={Login}/>
<Route path="*" component={Welcome}/>
</Route>
</Router>
);
// init file:
var RouterContext = ReactRouter.RouterContext
var match = ReactRouter.match
match({
routes: Routes,
location: document.location.pathname
}, (err, redirectLocation, renderProps) => {
ReactDOM.render(<RouterContext {...renderProps} />, document.querySelector('#app'));
});
Markup is generated correctly, but the problem is: Clicking in Links doesn't work at all.
I am doing something wrong?
My libs:
"react": "0.14.7",
"react-dom": "0.14.7",
"react-router": "2.0.0"
JSFIDDLE: https://jsfiddle.net/Lp3gzott/ (same code but babelified)
I found the solution in react-router documentation. According to Server Rendering Guide:
In back end set:
match({ routes, location: req.url }, (err, redirectLocation, renderProps) => {
renderToString(<RouterContext {...renderProps} />
})
Notice RouterContext instead of Router and lack of history field in match params
In front-end:
match({ history, routes }, (error, redirectLocation, renderProps) => {
ReactDOM.render(<Router {...renderProps} />, mountNode)
})
Notice lack of location param for match
In routes file:
export <Route instead of <Router
Error React attempted to reuse markup in a container but the checksum was invalid. is not showing up again.
Links are working like a charm!
match() is a Server side rendering construct, its intentional static, because on the server you only ever respond to a single route at a time. On the client you want to actually render a Router component
ReactDOM.render((
<Router>
{ Routes }
</Router>
), document.querySelector('#app'))
Your, markup mismatch is probably due to a different issue, and you might want to check out one of the many "universal react" starters.