React Router 4 points to primary domain not subfolder - javascript

I have an app which is within a sub folder of my primary domain. So Test.com is my domain and my app is in a folder called 'Player' in that domain i.e Test.com/player.
The problem is React Router points to Test.com when it needs to point to Test.com/player.
The other issue is my index file is in a folder called 'public'.
How do I do this in React Router 4/htacess?
Thanks
App
import React from "react";
import {render} from "react-dom";
import {BrowserRouter, Route, Switch, hashHistory} from "react-router-dom";
import Nav from "./components/Nav";
import Home from "./components/Home";
import About from "./components/About";
import Contact from "./components/Contact";
class App extends React.Component {
render() {
return (
<BrowserRouter history={hashHistory}>
<div>
<Nav />
<Switch>
<Route exact path="/" component={Home} />
<Route path="/about" component={About} />
<Route path="/contact" component={Contact} />
<Route render={() => {
return <h1>Not Found!</h1>
}} />
</Switch>
</div>
</BrowserRouter>
);
}
}
render(<App />, document.getElementById("main"));
Webpack
const webpack = require("webpack");
module.exports = {
entry: {
filename: "./app/app.js"
},
output: {
filename: "./app/build/bundle.js"
},
module: {
loaders: [
{
test: /\.js$/,
exclude: /node_modules/,
loader: "babel-loader",
query: {
presets: ["es2015", "react"]
}
}
]
},
devServer: {
inline: true,
port: 5000,
contentBase: "./public",
historyApiFallback: true,
}
}

According to React Router Docs, BrowserRouter has
basename: string The base URL for all locations. If your app is served
from a sub-directory on your server, you’ll want to set this to the
sub-directory. A properly formatted basename should have a leading
slash, but no trailing slash.
you can use
class App extends React.Component {
render() {
return (
<BrowserRouter history={hashHistory} basename="/player">
<div>
<Nav />
<Switch>
<Route exact path="/" component={Home} />
<Route path="/about" component={About} />
<Route path="/contact" component={Contact} />
<Route render={() => {
return <h1>Not Found!</h1>
}} />
</Switch>
</div>
</BrowserRouter>
);
}
}
You also need those properties on your webpack.config.js
module.exports = {
entry : 'your entry',
output : {
path : 'your path',
filename : 'your filename',
publicPath : '/' //ADD THIS LINE (either / or /player will work)
},
devServer : {
historyApiFallback : true // ADD THIS LINE
}
}

Related

Error: Absolute route path "/" nested under path "/app" is not valid

I suddenly get this error and not sure why.I did not change the "react-router-dom": "^6.0.0-beta.4" version. But the "react-dom": "^16.8.4"" had changed to "react-dom": "^16.13.1",
Dunno if that had anything to do with I don't know but the useRoutes comes from "react-router-dom" and that's where the error originate ya.
Anyone have a clue?
Here is my App.jsx where i use the useRoutes(routes) and it's giving me the error:
import React, { useEffect } from 'react';
import { AnimatePresence } from 'framer-motion';
import { connect } from 'react-redux';
import { compose } from 'recompose';
import { useRoutes } from 'react-router-dom';
import { ThemeContextProvider } from './theme/ThemeProvider';
import { getAlbumData } from './redux/albumData/albumData.actions';
import { getMetaData } from './redux/albumMetaData/albumMetaData.actions';
import {
startTagsListener,
startTagsCategoryListener,
} from './redux/global/global.actions';1111
import { withAuthentication } from './session';
import './styles/index.css';
import routes from './routes';
require('react-dom');
const AnimatedSwitch = () => {
const routing = useRoutes(routes);
return (
<AnimatePresence exitBeforeEnter initial={false}>
<div>{routing}</div>
</AnimatePresence>
);
};
const App = props => {
const { getMeta, getAlbum, startTagListener, startTagCategoryListener } = props;
useEffect(() => {
getMeta();
getAlbum();
startTagListener();
startTagCategoryListener();
}, [getMeta, getAlbum, startTagListener, startTagCategoryListener]);
return (
<ThemeContextProvider>
{AnimatedSwitch()}
</ThemeContextProvider>
);
};
const mapDispatchToProps = dispatch => ({
getMeta: () => dispatch(getMetaData()),
getAlbum: () => dispatch(getAlbumData()),
startTagListener: () => dispatch(startTagsListener()),
startTagCategoryListener: () => dispatch(startTagsCategoryListener()),
});
export default compose(connect(null, mapDispatchToProps), withAuthentication)(App);
Here are the routes and I have not changed them in the last month:
import React from 'react';
import ContentLayout from './components/structure/ContentLayout';
import DashboardLayout from './components/DashboardLayout';
import AccountView from './components/DashboardLayout/views/account/AccountView';
import SearchListView from './components/DashboardLayout/views/search/SearchListView';
import DashboardView from './components/DashboardLayout/views/dashboard/DashboardView';
import NotFoundView from './components/DashboardLayout/views/errors/NotFoundView';
import CreateContentView from './components/DashboardLayout/views/creator/CreateContentView';
import SettingsView from './components/DashboardLayout/views/settings/SettingsView';
import LoginView from './components/DashboardLayout/views/auth/LoginView';
import RegisterView from './components/DashboardLayout/views/auth/RegisterView';
import SubmissionsView from './components/DashboardLayout/views/submissions/SubmissionsView';
import InboxView from './components/DashboardLayout/views/inbox/InboxView';
const routes = [
{
path: 'app',
element: <DashboardLayout />,
children: [
{ path: 'account', element: <AccountView /> },
{ path: 'search', element: <SearchListView /> },
{ path: 'dashboard', element: <DashboardView /> },
{ path: 'create', element: <CreateContentView /> },
{ path: 'submissions', element: <SubmissionsView /> },
{ path: 'inbox', element: <InboxView /> },
{ path: 'settings', element: <SettingsView /> },
{ path: 'login', element: <LoginView /> },
{ path: 'register', element: <RegisterView /> },
{ path: '*', element: <NotFoundView /> },
{ path: '/', element: <DashboardView /> },
],
},
{
path: '/',
element: <ContentLayout />,
children: [
{ path: '404', element: <NotFoundView /> },
{ path: '*', element: <NotFoundView /> },
],
},
];
export default routes;
I have had a similar issue with material kit ui, and i fixed it simply just write path:"". leaving the path empty will fix the problem
I have same issue.I fixed it that change '/' to '' or '/' to index.
<Routes>
<Route path='/' element={<Home/>} />
<Route path='Chart' element={<Charts/>}>
<Route path='' element={<ChartList/>}/>
<Route path=':slug' element={<Chart/>}/>
</Route>
<Route path='*' element={<ErrorPage/>} />
</Routes>
or
<Routes>
<Route path='/' element={<Home/>} />
<Route path='Chart' element={<Charts/>}>
<Route index element={<ChartList/>}/>
<Route path=':slug' element={<Chart/>}/>
</Route>
<Route path='*' element={<ErrorPage/>} />
</Routes>
I have seen the error message and it clearly explains that path "/" should not be given under route "app".So try changing the path to some other valid name or remove it.
Just remove the last child path "/" and it will fix the problem.
In the case you are nesting Routes, one workaround is to group them together:
From
<BrowserRouter>
<Routes>
<Route path="/" element={<LandingPage />} />
<Route path="products" element={<Foo/>}
<Route path="/" element={<Bar/>}/>
<Route path=":id" element={<FooBar/>}/>
</Route>
</Routes>
</BrowserRouter>
To
<BrowserRouter>
<Routes>
<Route path="/" element={<LandingPage />} />
<Route path="products/:id" element={<Product />}/>
</Routes>
</BrowserRouter>

React JS - React-Router nested route

I'm new on React and I try to build my first application, for the route I used react-router and this is my App
class App extends Component {
render() {
return (
<Router history={browserHistory}>
<Route path='/' component={Container}>
<IndexRoute component={Home}/>
<Route path='/address' component={Address}>
<IndexRoute component={TwitterFeed} />
<Route path='instagram' component={Instagram} />
<Route path='query' component={Query} />
</Route>
<Route path='/about/:name' component={About} />
<Route path='/namedComponent' component={NamedComponents}>
<IndexRoute components={{ title: Title, subTitle: SubTitle }} />
</Route>
<Route path='*' component={NotFound} />
</Route>
</Router>
)
}
}
Everything work well but not this line <Route path='/about/:name' component={About} />, in fact if i try to write /address/12345 white page appears to me whitout error, someone can help me?
This is my webpack.config.js
'use strict';
var ExtractTextPlugin = require('extract-text-webpack-plugin');
var webpack = require('webpack');
module.exports = {
entry: {
app: [
'./src/main.js'
]
},
output: {
path: __dirname + '/dist',
publicPath : '/',
filename: 'bundle.js'
},
plugins: process.env.NODE_ENV === 'production' ? [
new webpack.optimize.DedupePlugin(),
new webpack.optimize.OccurrenceOrderPlugin(),
new webpack.optimize.UglifyJsPlugin(),
new ExtractTextPlugin({ filename: '[name].css', disable: false, allChunks: true})
] : [],
devServer: {
contentBase: "./dist",
inline: true,
port: 3000,
},
//source map for js
devtool: 'source-map',
module: {
loaders: [
//babel ECMAScript 6 compiler
{
test: /\.js?$/,
exclude: /node_modules/,
loader: 'babel-loader'
},
{
test: /\.scss$/,
loaders: [ 'style-loader', 'css-loader?sourceMap', 'sass-loader?sourceMap' ] //sourceMap for debug css in devTools
/*loader: ExtractTextPlugin.extract({
fallback : 'style-loader', use : 'css-loader?sourceMap!sass-loader?sourceMap'
}) FOR PROD*/
}
]
},
}
And i use this script : webpack-dev-server --inline --content-base dist --history-api-fallback
In your component "Container" you should have children object.
You can have a better look on the snippet bellow.
import React from 'react';
import { BrowserRouter as Router, Route } from 'react-router-dom';
const BasicExample = () =>
<Router>
<div>
<ul>
<Route to="/" component={ComponentThatHaveChildren} />
<Route path="/path1/path2" component={ChildrenComponent} />
</ul>
</div>
</Router>;
const ComponentThatHaveChildren = props =>
<div>
<h1>Component That Have Children</h1>
<h2>{props.children}</h2>
</div>;
const ChildrenComponent = () =>
<div>
<h2>Children</h2>
</div>;
export default BasicExample;

React: App not rendering to screen when wrapped in React.Component

So, my app, after being wrapped in a class, no longer renders to the screen, and no errors are issued. Just a blank screen is displayed.
What am I overlooking here?
webpack.config
var path = require('path');
var webpack = require('webpack');
const Dotenv = require('dotenv-webpack');
module.exports = {
devtool: 'source-map',
entry: [
'webpack-hot-middleware/client',
'./client/index'
],
output: {
path: path.join(__dirname, 'public'),
filename: 'bundle.js',
publicPath: '/static/'
},
plugins: [
new webpack.HotModuleReplacementPlugin(),
new webpack.NoEmitOnErrorsPlugin(),
new Dotenv({
path: './.env', // Path to .env file (this is the default)
safe: true // load .env.example (defaults to "false" which does not use dotenv-safe)
})
],
module: {
rules: [
// js
{
test: /\.js$/,
use: ['babel-loader'],
include: path.join(__dirname, 'client')
},
// CSS
{
test: /\.styl$/,
include: path.join(__dirname, 'client'),
use: [
'style-loader',
'css-loader',
'stylus-loader'
]
}
]
}
};
index.js
import React from 'react';
import ReactDOM from 'react-dom';
import app from './app.js';
ReactDOM.render (
<app />,
document.getElementById('root')
)
app.js
import React from 'react';
import { render } from 'react-dom';
import { Provider } from 'react-redux';
import { Router, Route, IndexRoute, Redirect } from 'react-router'
import 'babel-polyfill';
import { ApolloProvider, graphql, gql } from 'react-apollo';
import client from './apolloClient';
import App from './components/App';
import Single from './components/Single';
import PhotoGrid from './components/PhotoGrid';
import LoginUser from './components/LoginUser';
import css from './styles/style.styl';
import store, { history } from './store';
import Raven from 'raven-js';
import { sentry_url } from './data/config';
if(window) {
Raven.config(sentry_url).install();
}
import * as OfflinePluginRuntime from 'offline-plugin/runtime';
if (process.env.NODE_ENV === 'production') {
OfflinePluginRuntime.install();
}
class app extends React.Component {
render () {
return (
<ApolloProvider store={store} client={client}>
{ /* Tell the Router to use our enhanced history */ }
<Router history={history}>
<Route path="/" component={App}>
<IndexRoute component={PhotoGrid} />
<Route path="/view/:postId" component={Single}></Route>
<Route path="/login" component={LoginUser}></Route>
</Route>
</Router>
</ApolloProvider>
)
}
}
export default app;
But if I remove the class, as follows, and specify app.js as the entry: point in my webpack.config, then the app renders correctly:
render(
<ApolloProvider store={store} client={client}>
{ /* Tell the Router to use our enhanced history */ }
<Router history={history}>
<Route path="/" component={App}>
<IndexRoute component={PhotoGrid} />
<Route path="/view/:postId" component={Single}></Route>
<Route path="/login" component={LoginUser}></Route>
</Route>
</Router>
</ApolloProvider>,
document.getElementById('root')
);
All react classes in jsx must have a capital first letter. You need to update your index.js accordingly
import React from 'react';
import ReactDOM from 'react-dom';
import App from './app.js';
ReactDOM.render (
<App />,
document.getElementById('root')
)
If you were to look at the html output of your code you would likely see <app></app> where you expected your component to be inserted
what about try stateless component:
export default function App() {
return (
<ApolloProvider store={store} client={client}>
{ /* Tell the Router to use our enhanced history */ }
<Router history={history}>
<Route path="/" component={App}>
<IndexRoute component={PhotoGrid} />
<Route path="/view/:postId" component={Single}></Route>
<Route path="/login" component={LoginUser}></Route>
</Route>
</Router>
</ApolloProvider>
)
}

How get all defined routes from ReactRouter?

I define my routes like this:
window.myRoutes = ReactDOM.render((
<ReactRouter.Router history={ReactRouter.browserHistory}>
<ReactRouter.Route path="/" component={Home}>
<ReactRouter.IndexRoute
component={Main}
/>
<ReactRouter.Route
path="/subpath"
component={SubPath}
/>
<ReactRouter.Route
path="/subpath2"
component={SubPath2}
/>
</ReactRouter.Route>
</ReactRouter.Router>
), document.getElementById( "main" ) );
But when I try to access that in another component's componentDidMount(), it's undefined:
componentDidMount() { console.log( window.myRoutes ); }
How do I get all the routes defined?
NOTE: I do not just want the routes in this.props.routes as that's just all the routes leading to the current one
With React Router v2/3, the <Route> components don't actually render anything. They are just converted to an object which the <Router> uses to match against the current location's pathname. If you want to have an object containing all of your routes, it is easy enough to define them as an object.
<Router history={browserHistory}>
<Route path="/" component={Home}>
<IndexRoute component={Main} />
<Route path="/subpath" component={SubPath} />
<Route path="/subpath2" component={SubPath2} />
</Route>
</Router>
is equivalent to
var routes = {
path: '/',
component: Home,
indexRoute: {component: Main}
childRoutes: [
{
path: 'subpath',
component: Subpath
},
{
path: 'subpath2',
component: Subpath2
}
]
}
<Router history={browserHistory} routes={routes} />

react-route,react-hot-loader.webpack (You cannot change <Router routes>; it will be ignored)

it's my first project that use react,react-router,react-hot-loader,webpack-dev-server and webpack. when I change the code in react component, the hot-loader become effective, but at the same time, the console tell me a warning:
You cannot change 《Router routes》; it will be ignored.
I don't know how to solve this issue.there is code:
webpack code:
var path = require('path');
var webpack = require('webpack');
module.exports = {
devtool: 'source-map' ,
entry: [
'webpack-dev-server/client?http://localhost:3000',
'webpack/hot/only-dev-server',
'./jsx/index'
],
output: {
path: path.join(__dirname, 'public'),
filename: 'bundle.js',
publicPath: '/public/'
},
plugins: [
new webpack.HotModuleReplacementPlugin(),
new webpack.NoErrorsPlugin()
],
resolve: {
extensions: ['', '.js', '.jsx', 'json']
},
module: {
loaders: [{
test: /\.js$/,
exclude: /node_modules/,
loaders: ['react-hot', 'babel'],
}]
},
watch:true
};
index code:
import React from 'react'
import ReactDOM from 'react-dom'
import { Router, Route, Link } from 'react-router'
import App from './index/app'
import About from './index/about'
import Inbox from './index/inbox'
class Routers extends React.Component {
render() {
return (
<Router>
<Route path="/" component={App}>
<Route path="about" component={About} />
<Route path="inbox" component={Inbox} />
</Route>
</Router>
);
}
}
ReactDOM.render(<Routers />, document.getElementById('root'));
thank you !!!!
Only thing you need to do, it's to throw <Route /> out of render() method.
So, there are many ways to solve this issue.
Most Official way is what #Stormy say.
My solution like this:
const routes = (
<Route path="/" component={App}>
<Route path="about" component={About} />
<Route path="inbox" component={Inbox} />
</Route>
)
// Don't let <Route> in render() method
class Routers extends React.Component {
render() {
return (
<Router>
{ routes }
</Router>
);
}
}
Try to use this configuration
https://github.com/reactjs/react-router/issues/2704#issuecomment-170940448
const routeConfig = [
{ path: '/:locale',
component: App,
indexRoute: { component: NewsCardsContainer },
...
}
];
return (
<IntlProvider key="intl" {...intlData}>
<Router history={history} routes={routeConfig} />
</IntlProvider>
)
Stormy's suggestion of using <Router routes={Routes}/> worked for me. Here are my warning free code snippits with react hot module replacement:
./index.js
import './globals';
import React from "react";
import ReactDOM from "react-dom";
import { AppContainer as HotContainer } from "react-hot-loader";
import { browserHistory } from 'react-router';
import Routes from "./components/Routes.jsx";
const render = function() {
let Router = require('react-router').Router;
ReactDOM.render(
<HotContainer>
<Router history={browserHistory} routes={Routes}/>
</HotContainer>,
document.getElementById('react-container'),
);
};
render();
if( module.hot ) {
module.hot.accept('./components/Routes', () => {
render();
});
}
./components/Routes.jsx
import React from "react";
import { Route, IndexRoute } from "react-router";
import App from "./App.jsx";
import Graphs from "./graphs/Graphs.jsx";
import Trends from "./trends/Trends.jsx";
import Patterns from "./patterns/Patterns.jsx";
const Routes = (
<Route path="/" component={App}>
<IndexRoute component={Graphs}/>
<Route path="graphs" component={Graphs}/>
<Route path="trends" component={Trends}/>
<Route path="patterns" component={Patterns}/>
</Route>
);
export default Routes;
The router actually should never change, so you should be able to just return false for shouldComponentUpdate() in this case.
import React from 'react'
import ReactDOM from 'react-dom'
import { Router, Route, Link } from 'react-router'
import App from './index/app'
import About from './index/about'
import Inbox from './index/inbox'
class Routers extends React.Component {
shouldComponentUpdate(){
return false;
}
render() {
return (
<Router>
<Route path="/" component={App}>
<Route path="about" component={About} />
<Route path="inbox" component={Inbox} />
</Route>
</Router>
);
}
}
My Solution is change "Reflux.Component" to "React.Component"
class AppRouter extends Reflux.Component {
constructor(props){
super(props);
this.store = AuthStore;
}
requireAuth (nextState, replace, callback) {
if (nextState.location.pathname != '/login' && nextState.location.pathname != '/logout') {
ActionsAuth.jwt.refresh();
}
const token = UtilsJWT().getToken();
if (token){
if (nextState.location.pathname == '/login') {
window.location.href = '/main';
}
callback();
}else{
if (nextState.location.pathname != '/login') {
window.location.href = '/login';
}
}
}
verifyAuth (nextState, replace, callback) {
const token = UtilsJWT().getToken();
if (token){
if (nextState.location.pathname == '/login') {
window.location.href = '/main';
}
callback();
}else{
if (nextState.location.pathname != '/login') {
window.location.href = '/login';
}
callback();
}
}
render(){
return (
<Router history={browserHistory}>
<Route path="/" component={App}>
<IndexRoute component={Login} onEnter={ this.verifyAuth }/>
<Route path="login" component={Login} onEnter={ this.verifyAuth }/>
<Route path="main" component={Main} onEnter={ this.requireAuth }/>
<Route path="logout" component={Logout} onEnter={ this.requireAuth }/>
<Route path="local-sync" component={LocalSync} onEnter={ this.requireAuth }/>
<Route path="*" component={Login} onEnter={ this.verifyAuth }/>
</Route>
</Router>
)
}
}
i have the same issue,my Solution is change "import { Router, Route, Link } from 'react-router'" to "import {HashRouter, Route, Link} from 'react-router-dom'"
my code:
ReactDOM.render((
<HashRouter>
<div>
<ul>
<li><Link to="/">Home</Link></li>
<li><Link to="/login">Login</Link></li>
</ul>
<hr/>
<Route path="/" exact component={createComponent(Home)}/>
<Route path="/login" component={createComponent(Login)}/>
</div>
</HashRouter>
), document.getElementById('root'));
I know this is an old question, but someone might find this useful. I tried a lot of stuff and what finally worked for me is:
import React from 'react'
import ReactDOM from 'react-dom'
import { Router, Route, Link } from 'react-router'
import App from './index/app'
import About from './index/about'
import Inbox from './index/inbox'
class Routers extends React.Component {
private routes = (
<Route path="/" component={App}>
<Route path="about" component={About} />
<Route path="inbox" component={Inbox} />
</Route>
);
render() {
return (
<Router>
{this.routes}
</Router>
);
}
}

Categories