I try to use react-router-dom 4.0.0 library. But it send me this error
Uncaught TypeError: Cannot read property 'location' of undefined
It seems that problem in browserHistore. Before I used react-router 2.x.x and everything was alright.
This is my index.js
import 'babel-polyfill'
import React from 'react'
import { Router, hashHistory } from 'react-router-dom'
import { render } from 'react-dom'
import { Provider } from 'react-redux'
import { configureStore } from './store'
import { routes } from './routes'
const store = configureStore()
render(
<Provider store={store}>
<Router history={hashHistory} routes={routes} />
</Provider>,
document.getElementById('root')
)
This is my routes
import React from 'react'
import { IndexRoute, Route } from 'react-router-dom'
import App from './containers/App'
import Main from './containers/Main'
import First from './containers/First'
export const routes = (
<Route path='/' component={Main}>
<Route path='/path' component={First} />
<IndexRoute component={App} />
</Route>
)
And also for server side express I set this get configuration
app.get('*', function root(req, res) {
res.sendFile(__dirname + '/index.html');
});
React Router v4 is a complete re-write and isn't compatible with previous versions as you're assuming in your code. With that said, you shouldn't expect to be able to just upgrade to a new major version (V4) and have your app work as normal. You should check out the documentation or downgrade back to V2/3. Here's some code that should get you started in the right direction
import 'babel-polyfill'
import React from 'react'
import { BrowserRouter as Router, Route } from 'react-router-dom'
import { render } from 'react-dom'
import { Provider } from 'react-redux'
import { configureStore } from './store'
import App from './containers/App'
import Main from './containers/Main'
import First from './containers/First'
const store = configureStore()
render(
<Provider store={store}>
<Router>
<Route path='/' component={Main} />
<Route path='/path' component={First} />
</Router>
</Provider>,
document.getElementById('root')
)
Check the version of react-router-dom in package.json
If its version is greater than 4 then in your file import BrowserRouter :-
import { BrowserRouter as Router, Route } from 'react-router-dom'
else if its version is less than 4 then import Router :-
import { Router, Route } from 'react-router-dom'
Install npm history package: npm i history
and then use it as follow in your index/routes file:
import React from 'react';
import ReactDOM from 'react-dom';
import { Router, Switch, Route} from 'react-router-dom';
import createBrowserHistory from 'history/createBrowserHistory';
import App from './components/App';
import './index.css'
const history = createBrowserHistory();
ReactDOM.render(
<Router history={history}>
<Switch>
<Route path='/' component={App}/>
</Switch>
</Router>,
document.getElementById('root')
);
Related
index.js
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
ReactDOM.render(<App />, document.querySelector('#root'));
App.js
import React from 'react';
import { BrowserRouter, Routes, Route } from 'react-router-dom';
import Join from './components/Join';
import Chat from './components/Chat';
const App = () => (
<Routes>
<Route path='/' exact component={Join} />
<Route path='/chat' component={Chat} />
</Routes>
);
export default App;
It thows error like "Error: useRoutes() may be used only in the context of a component."
Here is the ERROR:
"
You have to wrap your app in the BrowserRouter component in order to be able to use routing
So the code in index.js will be as follows
import React from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter } from 'react-router-dom';
import App from './App';
ReactDOM.render(<BrowserRouter> <App /> </BrowserRouter>, document.querySelector('#root'));
You could instead wrap the app in App.js
import React from 'react';
import { BrowserRouter, Routes, Route } from 'react-router-dom';
import Join from './components/Join';
import Chat from './components/Chat';
const App = () => (
<BrowserRouter>
<Routes>
<Route path='/' exact component={Join} />
<Route path='/chat' component={Chat} />
</Routes>
</BrowserRouter>
);
export default App;
but for cleaner code, do the first approach
Wrap your code inside <BrowserRouter> making sure it isn’t in the app itself but higher up in the tree.
I currently have a react app I am working on and the routing is buggy. I have set up react applications and their routings like this before but when trying to route to the "details" component, only the url changes, but the component does not load. An extra pair of eyes would be nice to see what I'm missing. I have the routes set up as:
index.js:
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import { Router } from "react-router-dom";
import { createBrowserHistory } from "history";
const history = createBrowserHistory();
const render = () => {
ReactDOM.render(
<Router history={history}>
<App />
</Router>,
document.getElementById('root'),
);
};
render();
App.js:
import React from 'react';
import {Route, Switch} from 'react-router-dom';
import { BreweryPage } from './route.js';
function App() {
return (
<>
<Switch>
<Route exact path="/" component={BreweryPage}/>
</Switch>
</>
);
}
export default App;
route.js
import React from 'react';
import PropTypes from 'prop-types';
import { Route, Switch, withRouter } from 'react-router-dom';
import { BreweryPage, BreweryDetailPage } from './pages';
import {AppContainer} from "../../common/header";
const BreweryHomePage = ({ match }) => (
<AppContainer>
<Switch>
<Route exact path={`${match.url}`} component={BreweryPage} />
<Route exact path={`${match.url}/details/:breweryid`} component={BreweryDetailPage} />
</Switch>
</AppContainer>
);
BreweryHomePage.propTypes = {
match: PropTypes.shape({
url: PropTypes.string,
}),
};
BreweryHomePage.defaultProps = {
match: {
url: '',
},
};
export default withRouter(BreweryHomePage);
The root "/" path component loads, but I can't get the details components component to render when routing with history.push(path) using const history = useHistory();.
do it like this
1-index.js should like this:
import React from "react"
import ReactDOM from "react-dom"
import App from "./App"
import { BrowserRouter } from "react-router-dom"
const app = (
<React.StrictMode>
<BrowserRouter>
<App />
</BrowserRouter>
<React.StrictMode/>
)
ReactDOM.render(app, document.getElementById("root"))
you have to add BrowserRouter to be able to use navigation
2- you can use BreweryPage in App.js like this:
import React from 'react';
import {Route, Switch} from 'react-router-dom';
import { BreweryPage } from './route.js';
function App() {
return (
<>
<BreweryPage/>
</>
);
}
export default App;
3- route.js
import React from 'react';
import PropTypes from 'prop-types';
import { Route, Switch, withRouter } from 'react-router-dom';
import { BreweryPage, BreweryDetailPage } from './pages';
import { createBrowserHistory } from "history";
import {AppContainer} from "../../common/header";
const newHistory = createBrowserHistory();
const BreweryHomePage = (props) => (
<Router history={newHistory}>
<Switch>
<Route exact path="/" component={BreweryPage} />
<Route path="/details/:breweryid" component={BreweryDetailPage} />
</Switch>
</Router>
);
export default withRouter(BreweryHomePage);
i am trying to make a navigaton on my website by react-router and typescript. but its not working and instead of Home page i get an empty page
Thats my app.tsx file
// app.tsx
import * as React from 'react';
import '../App.css';
class App extends React.Component<any,any> {
public render() {
return (
<div>
{this.props.children}
</div>
);
}
}
export default App;
index.tsx
// index.tsx
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import './index.css';
import registerServiceWorker from './registerServiceWorker';
import {AppRouter} from './router';
ReactDOM.render(
<AppRouter/>,
document.getElementById('root') as HTMLElement
);
registerServiceWorker();
router.tsx
import * as React from 'react';
import { Route,Router } from 'react-router';
import App from './components/App';
import HomePage from './components/home/HomePage';
import createHistory from 'history/createBrowserHistory';
const history = createHistory();
export const AppRouter = () => {
return (
<Router history={history}>
<Route path="/" component={App} >
<Route path="/" exact={true} component={HomePage} />
</Route>
</Router>
);
}
i dont really dont know what to say. i cant find any possible info about this. If u know better way to make navigation with typescript, react and redux i am open for ideas. thx
In the App component, you are doing {this.props.children}. So you should not pass that component to any route.
You need to add all the routes as a child of that component through which you will get the children in your props.
Also, for switching between routes, you should bind all the routes in the 'Switch' imported from react-router.
So, your router.tsx file should look like:
import * as React from 'react';
import { Route, Router, Switch } from 'react-router';
import App from './components/App';
import OtherComponent from './components/OtherComponent';
import HomePage from './components/home/HomePage';
import createHistory from 'history/createBrowserHistory';
const history = createHistory();
export const AppRouter = () => {
return (
<App>
<Router history={history}>
<Switch>
<Route exact={true} component={HomePage} />
<Route path="/other" component={OtherComponent} />
</Switch>
</Router>
</App>
);
}
By this, you will get the 'HomePage' component at route '/' and OtherComponent at route '/other'.
I setup simple route within my index.js file.
import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import { createStore, applyMiddleware } from 'redux';
import { Router, Route, IndexRoute, browserHistory } from 'react-router';
import reduxThunk from 'redux-thunk';
import '../less/app.less';
import reducers from './reducers';
import App from './components/App';
import Login from './components/auth/Login';
import Welcome from './components/Welcome';
// const defaultSetting = settings;
const createStoreWithMiddleware = applyMiddleware(reduxThunk)(createStore);
ReactDOM.render(
<Provider store={createStoreWithMiddleware(reducers)}>
<Router history={browserHistory}>
<Route path="/" component={App}>
<IndexRoute component={Welcome} />
<Route path="login" component={Login} />
</Route>
</Router>
</Provider>
, document.querySelector('.container')
);
my App.js
import React, { Component } from 'react';
class App extends Component {
render() {
return (
<div>
{this.props.children}
</div>
);
}
}
export default App;
When I navigate to localhost:8080 using webpack-dev-server I can properly show my index route. but when I navigate to localhost:8080/login' it shows errorCannot GET /login`.
Any solution?
By default the server will look for an html file at the /login route. So you should configure it for html5 navigation to return you index.html for any route it receives.
EDIT:
To do so in webpack, as you suggest in the comments, you can add this to your webpack dev server config:
historyApiFallback: true
index.html should be the default, so no need to specify it.
Also please note that urls containing dots are still pointing to files and thus redirected to the server. For example, if you have an url such as /search/firsname.lastname you would need to add a handler for this.
historyApiFallback: {
rewrites: [
{
from: /^\/search\/.*$/,
to: function() {
return 'index.html';
}
}
]
},
See this issue for more info.
Currently my URL structure is still storing history in hash syntax.
Ex: http://localhost:3000/#/work?_k=otstr8
Im trying to have it use browserHistory from react-router to be displayed as:
http://localhost:3000/#/work
Here is my routes.js file:
//Import Dependencies.
import React from 'react';
import { Router, Route } from 'react-router'
import ReactDOM from 'react-dom';
//Import Components.
import AboutElement from '../views/about/about.jsx';
import WorkElement from '../views/work/work.jsx';
import ResumeElement from '../views/resume/resume.jsx';
//Set up routes.
let routes = (
<Router>
<Route path='/' component={AboutElement}/>
<Route path='/work' component={WorkElement}/>
<Route path='/resume' component={ResumeElement}/>
</Router>
);
export default routes;
My index.js file:
//Import Dependencies.
import React from 'react';
import ReactDOM from 'react-dom';
import { Router, browserHistory } from 'react-router';
//Import Routes.
import routes from './routes/routes.js';
ReactDOM.render(<Router history={browserHistory} routes={routes} />, document.getElementById('application'))
From what I have researched this syntax is correct for browserHistory? For some reason hash history is still being used. Any ideas why this is still happening?
Just install history as a seperate library and use this.
import { createHistory } from 'history'
const history = createHistory()
Just created my own variable for browserHistory.
//Import Dependencies.
import React from 'react';
import ReactDOM from 'react-dom';
import { Router } from 'react-router';
import createBrowserHistory from 'history/lib/createBrowserHistory';
const browserHistory = createBrowserHistory();
//Import Routes.
import routes from './routes/routes.js';
ReactDOM.render(<Router history={browserHistory} routes={routes} />, document.getElementById('application'));
The syntax for the url is now:
localhost:3000/
localhost:3000/work
localhost:3000/resume
Which is great!