Steps to reproduce
client.js (entry file)
import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import { createStore, applyMiddleware } from 'redux';
import { Router, browserHistory } from 'react-router';
import reduxThunk from 'redux-thunk';
import reducers from './reducers';
import routes from './routes.js';
const storeWithMiddleware = applyMiddleware(reduxThunk)(createStore);
const store = storeWithMiddleware(reducers);
ReactDOM.render(
<Provider store={store}>
<Router history={browserHistory} routes={routes} />
</Provider>, document.getElementById('app')
);
routes.js (ver 1)
import React from 'react';
import { Route, IndexRoute } from 'react-router';
import App from './components/bases/app.js';
import Login from './components/app/authentication/login.js';
export default(
<Route path="/" component={App}>
<Route path="signup" component={Login}/>
</Route>
)
routes.js (ver 2)
let routes = {
path: '/',
component: App,
childRoutes: [
{ path: 'signup', component: Login }
]
}
export default routes;
Expected Behavior
Expect to have /signup route avail.
Actual Behavior
react-router cannot find the route /signup but can find /
Having a look at the chrome dev-tools source-tab, this is what I find:
When looking at "/"
sources
--------
dist/prod
| bundle.js
index.html
When looking at "/signup"
sources
--------
signup
If you changed to hashHistory and it worked it probably be your backend which serves the html...
Since hashHistory works like this:
example.com/#/signup
The browser doesn't understand as a new GET, if you use browseHistory, this:
example.com/signup
Makes the browser request for index.html again but on path /signup ... but the webpack dev server probably don't understand..
Try adding historyApiFallback: true to webpack config
LIke this
https://github.com/amacneil/react-router-webpack-history-example
The giveaway is the files that are being served when you are looking at the sources. When you are trying to load the /signup page, your browser is trying to load a signup page.
When you use browserHistory, you need to serve your index.html (and any scripts included in it) for all possible routes. This means that you need to have a server which accepts all possible routes and responds accordingly.
For example, if you are running a node server using express, you would need to have a wildcard route handler:
// define static handler first for .js, etc.
app.use(express.static(path.join(__dirname, 'public')));
// all other routes should server your index.html file
app.get("/", handleRender);
app.get("*", handleRender);
function handleRender(req, res){
res.sendFile(__dirname + '/index.html');
}
Related
first of all i'd like to say that i'm a new developer of React and NodeJS.
I want use this technologies:
- React as a client
- NodeJS as a server
- Webpack for build my files.
My project structure is the follow:
my-application/
webpack.server.js
webpack.client.js
server.js
client/client.js
client/app.js
client/components/header.js
client/components/mainLayout.js
client/components/footer.js
The header and footer files are not important so i'm not writing here.
The important file are the following:
mainLayout.js
import React, { Component } from 'react';
// import component
import Header from './header';
import Footer from './footer';
class MainLayout extends React.Component {
constructor (props) {
super(props)
}
render() {
return (
<div className="App">
<Header />
{this.props.children}
<Footer />
</div>
);
}
}
export default MainLayout;
app.js
import React, { Fragment } from 'react';
import { Route, Switch } from 'react-router-dom';
import MainLayout from './components/mainLayout'
const AppComponent = () =>
<Switch>
<Route path="/" exact render={props => (
<MainLayout>
<h1>Hello World</h1>
</MainLayout>
)} />
</Switch>
;
export default AppComponent;
client.js
import 'babel-polyfill';
import React from 'react';
import ReactDOM from 'react-dom';
import {BrowserRouter} from 'react-router-dom';
import AppComponent from './app';
ReactDOM.hydrate(
<BrowserRouter>
<AppComponent />
</BrowserRouter>,
document.querySelector('#root')
);
server.js
import express from 'express';
import React from 'react';
import AppComponent from './client/app'
var app = express();
const PORT = 3000;
app.use("/", express.static("build/public"));
app.get("/", (req, res) => {
res.send(<AppComponent />)
});
app.listen(PORT, () => console.log('Now browse to localhost:3000'));
Run my project:
npm run build
npm run dev
but when i'm going at http://localhost:3000 my page response is
{"key":null,"ref":null,"props":{},"_owner":null,"_store":{}}.
I don't understand why i have the error, something probably escapes me but i don't what.
Can you help me please?
Thanks you in advance,
AS
You are running both front and back end on the same port. Go to package.json for your react app and replace your start script with the following script:
"scripts": {
"start": "set PORT=3007 && react-scripts start",
// the rest of your scripts
}
This will be the first step for resolving your issue. If you keep getting errors after that, let us know what are they.
I ran the application again using npm.
In the command I entered: npm start in the application folder after this it worked again.
In App.js, add Routes in the import. Use element instead of component.
For Example:
import {BrowserRouter, Routes, Route, Link, Switch} from 'react-router-dom'
<Navbar />
<BrowserRouter>
<Routes>
<Route path="/" exact element = {</>}/>
<Route path="/" exact element = {</>}/>
</Routes>
</BrowserRouter>
This can be from the browser you are using.
Copy the local host address on your address bar and paste on a different browser, Chrome recommended.
This is based on personal experience. It kept rolling on Opera browser until I opened it on Chrome.
I'm newbie in reactjs, I tried build something with it but I had problem with react-router-redux. I get React.createElement: type is invalid -- expected a string (for built-in components) or a class/function (for composite components) but got: undefined. in console. Here is my code :
App.js
import React, { PropTypes } from 'react';
class App extends React.Component {
render() {
return (
<div>
{this.props.children}
</div>
);
}
}
export default App;
Routes.js
import React from 'react';
import { Route, IndexRoute } from 'react-router'
import App from './components/App';
import Login from './components/login/Login';
import Register from './components/register/Register';
export default (
<Route path="/" component={App}>
<IndexRoute component={Login}/>
<Route path="register" component={Register}/>
</Route>
);
And Index.js
...
import { syncHistoryWithStore } from 'react-router-redux'
import { Router } from 'react-router'
import { createBrowserHistory } from 'history';
import routes from './routes';
const store = configureStore();
const history = syncHistoryWithStore(createBrowserHistory(), store)
ReactDOM.render(
<Provider store={store}>
<Router history={history} routes={routes}>
</Router>
</Provider>,
document.getElementById('app')
);
Where is my wrong? Please explain for me why I get this error. Thank in advance
React-router-redux is no longer maintained and support only 3.x and 2.x React-router versions
Repo authors suggest using connected-react-router for React-rotuer 4.x bindings
There are different routers for different environments, you want to use BrowserRouter instead of Router.
See React Training BrowserRouter for more information.
index.js
// change this line
import { Router } from 'react-router';
// to
import { BrowserRouter as Router } from 'react-router-dom';
NOTE: You might also have to pass in your routes in a different way. This is shown in the React Training page provided above.
I've got this piece of code as a router for my React 15.0.1 universal app. React router version is 2.3.0.
import React from 'react';
import { createHistory } from 'history';
import { Router, Route, IndexRoute, Redirect, useRouterHistory } from 'react-router';
import MainLayout from './../views/layout/mainLayout.jsx';
import Home from './../views/home.jsx';
import About from './../views/about.jsx';
import Error404 from './../views/404.jsx';
const browserHistory = useRouterHistory(createHistory)({
basename: '/example-url'
});
module.exports = (
<Router history={browserHistory}>
<Route path='/' component={MainLayout}>
<IndexRoute component={Home} />
<Route path='about/' component={About} />
<Route path='*' component={Error404} />
</Route>
</Router>
The problem is, that I'm getting the following error:
Invariant Violation: Browser history needs a DOM
It seems that this solution doesn't work for my server side routing, as I'm trying to set a basename for my routes.
If I forget about the basename, then everything is fine but my application doesn't behave like a spa (I believe that routes on client side are not found).
Here is some of my server side entry point (app.js):
import routes from './client/routers/routes.jsx';
const engine = ReactEngine.server.create({
routes: routes,
routesFilePath: path.join(__dirname, 'client/routers/routes.jsx'),
});
app.engine('.jsx', engine);
app.set('views', __dirname + '/client/views');
app.set('view engine', 'jsx');
app.set('view', ReactEngine.expressView);
app.get('*', function(req, res) {
res.render(req.url, { metadata: res.data.metadata,baseUrl: res.data.baseUrl, url: res.data.url });
});
Could anybody help please? I have read through the docs and supposedly this is the right way to do it and many people seem to support the solution but I'm stuck here.
Thank you very much
what's your history version?
if your react-router version is v2/v3, history version should be v3, v4 is for react-router v4
I'm using https://github.com/newtriks/generator-react-webpack to create an APP.
Everything is cool, I generate my dist files, but I upload my app on my website, like this: my-website.com/staging/my-app.
But when I navigate to my-website.com/staging/my-app it renders the error component, and If I press Home button, I see the homepage as excepted but the url in the navbar is my-website.com/.
If your website doesn't located in the root url, you will need to provide a basename option
For example:
import createBrowserHistory from "history/lib/createBrowserHistory"
import { Router, useRouterHistory } from "react-router"
const browserHistory = useRouterHistory(createBrowserHistory)({
basename: "staging/my-app",
})
// component
<Router history={ browserHistory } routes={ routes } />
I have installed React Router and am using browserHistory, but when I manually type the URL, I get Cannot GET /:path.
Any ideas why this might be?
index.js:
import React from 'react';
import ReactDOM from 'react-dom';
import {Router, browserHistory} from 'react-router';
import routes from './config/routes';
ReactDOM.render(<Router history={browserHistory} routes={routes} />, document.getElementById('app'));
routes.js
import React from 'react';
import {Route, IndexRoute} from 'react-router';
import App from '../components/app';
import Dashboard from '../components/dashboard';
import Expenditure from '../components/expenditure';
import Income from '../components/income';
import Transactions from '../components/transactions';
export default(
<Route path='/' component={App}>
<IndexRoute component={Dashboard} />
<Route path='expenditure' component={Expenditure} />
<Route path='income' component={Income} />
<Route path='transactions' component={Transactions} />
</Route>
);
Clicking on the nav displays the content perfectly with the correct route.
Am using webpack to compile with webpack-dev-server.
Thanks :)
You have to redirect all non-file requests to index.html, which is required for browserHistory to work.
In webpack-dev-server there is an option historyApiFallback, which you have to set to true to make it happen.
See webpack documentation for more information
new WebpackDevServer(compiler, {
historyApiFallback: true
// ...
})
I meet the same question today and cann't find answer in stackoverflow.
let path in webpack.config.js: output.publicPath be equal to devServer.historyApiFallback.index and point out html file route。my webpack-dev-server version is 1.10.1 and work well. http://webpack.github.io/docs/webpack-dev-server.html#the-historyapifallback-option doesn't work, you must point out html file route.
for example:
module.exports = {
entry: "./src/app/index.js",
output: {
path: path.resolve(__dirname, 'build'),
publicPath: 'build',
filename: 'bundle-main.js'
},
devServer: {
historyApiFallback:{
index:'build/index.html'
},
},
//其他的配置省略
};
historyApiFallback.index indicate that when url path not match a true file,webpack-dev-server use the file config in historyApiFallback.index to show in browser rather than 404 page. then all things about your route change let your js using react-router do it.