React TypeError: location is undefined - node.js

I am currently working on creating a boilerplate react application. I have been following these tutorials, but I haven't been able to get past the first tutorial.
I created my app with create-react-app
When I try to run my app, it compiles, but I get an error that says:
TypeError: location is undefined
This error points to the ReactDOM.render( line in this code
import React from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter } from 'react-router-dom';
import App from './App';
import registerServiceWorker from './registerServiceWorker';
ReactDOM.render(
<BrowserRouter>
<App />
</BrowserRouter>,
document.getElementById('root')
);
registerServiceWorker();
If it is relevant, here is my app.js file as well
import React from 'react';
import { Route } from 'react-router-dom';
import { HomePage, LoginPage } from "./components/pages";
import { Grid } from 'react-flexbox-grid';
import 'react-flexbox-grid/dist/react-flexbox-grid.css';
const App = () => (
<Grid fluid>
<Route path='/' exact component={HomePage} />
<Route path='/login' exact component={LoginPage} />
</Grid>
)
export default App;
I've also tried creating a new react app. For the first time, I ejected the app so that I could add css modules, then when I tried to build it again, I used custom react scripts. The problem began about when I ejected the app, but I'm sure if that was the problem because I did rebuild it and copy the src folder over to the new app.
Finally, here is a screenshot of the errors that I am getting.
I've been stuck on this problem for the past 2.5 days, so any help would be greatly appreciated. Thank you so much in advance.
UPDATE: Hey guys. I'm an idiot. The <Link> component uses a to attribute unlike the a tag's href. That was my problem. Really. Well there goes 3 days down the drain and all of your time. Thank you for your help anyway, I appreciate all that you have done.

EDIT - Explanation of the Resolution (as described in #Vishah's answer)
I'm adding an edit here in hopes of helping anyone who comes across this.
The source of the issue was the Links components included "href" attributes instead of "to" attributes.
- <Link href='/'>Home</Link>
+ <Link to='/'>Home</Link>
Additionally, it's worth noting the "href" didn't throw an attribute error because lowercase attributes are still valid dom in React ^16.2.
Here's the commit on his repo: https://github.com/vishalmshah/MERNStackBoilerplate/commit/73fb3fe2e39ffa870fb91bd8b3592887886e3dbb
This was not the source of the issue
I think I see the issue. BrowserRouter uses the location object to keep track of where you are, your history, and possibly other locations the app will navigate to.
BrowserRouter Routes require being given location object which they can use to compare their path value to.
You've got your Route's wrapped by your App object without passing the location object down.
Try passing location through your app:
const App = ({ location }) => (
Subsequently you may have to access the location in the Routes:
<Route location={location} ...
This example is where I got the information from:
https://github.com/Remchi/bookworm-react/blob/master/src/App.js

UPDATE: Hey guys. I'm an idiot. The component uses a to attribute unlike the a tag's href. That was my problem. Really. Well there goes 3 days down the drain and all of your time. Thank you for your help anyway, I appreciate all that you have done.

One thing I notice immediately is how you are importing the components...
import { HomePage, LoginPage } from "./components/pages";
You can not do this... Instead:
import HomePage from './components/pages/HomePage';
import LoginPage from './components/pages/LoginPage';
Also, you should not install react-router but just react-router-dom...
Here is the App.js
import React from 'react';
import { Route, Switch } from 'react-router-dom';
import HomePage from './HomePage';
import LoginPage from './LoginPage';
const App = () => (
<Switch>
<Route path="/" component={HomePage} exact={true} />
<Route path="/login" component={LoginPage} exact={true} />
</Switch>
);
export default App;
And here is the Index.js
import React from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter } from 'react-router-dom';
import App from './components/App';
import registerServiceWorker from './registerServiceWorker';
ReactDOM.render(
<BrowserRouter>
<App />
</BrowserRouter>,
document.getElementById('root'),
);
registerServiceWorker();
Note: I did not create the pages directory and am also using Switch... (docs: https://reacttraining.com/react-router/web/api/Switch)

Related

Creating admin user in MERN

I want to create an admin user in my MERN application, I created a user model on back-end and put isAdmin there. Now I want to protect some routes on back-end. On front-end I need to protect normal user to access admin panel, which is accessible when click on NavLink.
User schema:
Signup controller:
Front end routes:
you can use switch route of react routes like that.
import React from 'react';
import ReactDOM from 'react-dom';
import {
BrowserRouter as Router,
Route,
browserHistory,
Switch
} from 'react-router-dom';
import App from './app/App';
import Welcome from './app/Welcome';
import NotFound from './app/NotFound';
const isAdmin = false; // flag of current user login
const Root = () => (
<Router history={browserHistory}>
<Switch>
{{isAdmin ? <Route exact path="/admin" component={Admin}/> : null }}
{{isAdmin ? <Route exact path="/admin/new" component={AdminNew}/> : null }}
<Route component={NotFound}/>
</Switch>
</Router>
);
ReactDOM.render(
<Root/>,
document.getElementById('root')
);

react-router-dom giving 404 on multiple / in url

React router dom is throwing 404 on /blogs/new
But it works fine if i remove the second url like /blogs or any other single / url
import React from 'react';
import { BrowserRouter, Switch, Route } from 'react-router-dom';
import HomePage from './HomePage';
import Blogs from './Blogs';
import NewBlog from './NewBlog';
const Main = () => {
return (
<BrowserRouter>
<Switch>
<Route exact path='/blogs' component={Blogs} />
<Route path='/blogs/new' component={NewBlog} />
<Route exact path='/' component={HomePage} />
</Switch>
</BrowserRouter>
);
};
export default Main;
The code you have written seems fine. I tried a simple example on code sandbox with react-router-dom and seems to be working just as expected. You can check this out below and see if you are making some typo somewhere in your code -
It's probably possible that you are making some typo in writing your URLs in either the code or the browser because code-wise it seems correct to me.

Fetching API from react sending me wrong URL

Learning React.js and Node.js and making a simple crud app with Express API on the back-end and React.js on the front end.
App.js of my React.js looks like this.
`import React, { Component } from 'react';
import './App.css';
import Rentals from './components/Rentals';
import Idpage from './components/Idpage';
import {
BrowserRouter as Router,
Route,
Link
} from 'react-router-dom';
class App extends Component {
render() {
return (
<div className="mainappdiv">
<Router>
<main>
<Route exact path="/" component={Home} />
<Route exact path="/rentals" component={Rentals} />
<Route path="/rentals/:propertyid" component={Idpage} />
</main>
</div>
</Router>
</div>
);
}}
export default App;
I am making an app that when if you go to /rentals, it will fetch the data and print stuff. This is currently working and all the data from my database is rendering.
Now I am trying to go to /rentals/1 or /rentals/2 then trying to print only listings of that id.
import React, { Component } from 'react';
class Idpage extends Component {
componentDidMount() {
fetch('api/listofrentals/2')
.then((response)=>{
console.log(response)
return response.json()
})
.then((singlerent)=>{
console.log(singlerent)
})
}
render() {
return (
<div>
<p>this is the id page solo</p>
<p>{this.props.match.params.propertyid}</p>
</div>
);
}}
export default Idpage;
When I do this, I get an error saying GET http://localhost:3000/rentals/api/listofrentals/2 404 (Not Found)
I am trying to fetch from the URL http://localhost:3000/api/listofrentals/2 and do not understand why the "rentals" part is in the url.
My React server is running on localhost:3000 and node.js is running on localhost:30001. And my React's package.json has this "proxy": "http://localhost:3001/"
Fetch by default will access a relative path to where you are using it. You can specify you want to bypass the relative path by starting your url with /.
fetch('/api/listofrentals/2')
In case if you want to change the base url for testing. You can turn off web security in Google and use.
In ubuntu command line it is
google-chrome --disable-web-security --user-data-dir

React router shows blank page

I am trying to get started with react-router.
import React from 'react';
import ReactDOM from 'react-dom';
import HelloWorld from './pages/HelloWorld';
import {Router, Route, IndexRoute, hashHistory,browserHistory} from "react-router";
...
const app = document.getElementById('root')
ReactDOM.render(<HelloWorld/>, app);
Here dummy class HelloWorld:
import React, { Component } from 'react';
class HelloWorld extends Component {
render(){
return(<h1> HelloWorld </h1>);
}
}
export default HelloWorld;
Using this setting everything works out fine. However, using routes I end up having a blank page.
ReactDOM.render(
<Router history = {hashHistory}>
<Route path ="/" component={HelloWorld}>
</Route>
</Router>,
app);
Where is the mistake? I searched stackoverflow but no answer seems to be suitable.
Whats really weird for me, is that the following code also results in a blank page:
const Routes = () => (
<Router history = {browserHistory}>
<Route path ="/" render={ () => (<h1> HelloWorld </h1>) } />
</Router>
);
const app = document.getElementById('app')
ReactDOM.render(<Routes/>, app);
You're using using the V4 in a V3 way.
Instead of
import {Router, Route, IndexRoute, hashHistory,browserHistory} from "react-router";
Import dependencies in this way:
import {BrowserRouter as Router, Route} from "react-router";
import createHistory from "history/createBrowserHistory" // browser history moved into a standalone package since v4.
Ok "one" solution is:
import {BrowserRouter as Router, Route, IndexRoute,hashHistory,browserHistory} from "react-router-dom";
...
const Routes = () => (
<Router history = {browserHistory}>
<Route path ='/' component={ Layout } />
</Router>
);
const app = document.getElementById('app')
ReactDOM.render(<Routes/>, app);
99% sure your issue is that your tag has a relative link. Make it absolute.
<!-- do this -->
<script src="/static/bundle.js"></script>
<!-- not -->
<script src="static/bundle.js"></script>
<!-- or -->
<script src="./static/bundle.js"></script

Testing React Router with Jest and Enzyme

My goal is to test my React Router Route exports in my app and test if it is loading the correct component, page, etc.
I have a routes.js file that looks like:
import React from 'react';
import { Route, IndexRoute } from 'react-router';
import { App, Home, Create } from 'pages';
export default (
<Route path="/" component="isAuthenticated(App)">
<IndexRoute component={Home} />
<Route path="create" component={Create} />
{/* ... */}
</Route>
);
Note: isAuthenticated(App) is defined elsewhere, and omitted.
And from what I've read, and understood, I can test it as such:
import React from 'react';
import { shallow } from 'enzyme';
import { Route } from 'react-router';
import { App, Home } from 'pages';
import Routes from './routes';
describe('Routes', () => {
it('resolves the index route correctly', () => {
const wrapper = shallow(Routes);
const pathMap = wrapper.find(Route).reduce((pathMapp, route) => {
const routeProps = route.props();
pathMapp[routeProps.path] = routeProps.component;
return pathMapp;
}, {});
expect(pathMap['/']).toBe(Home);
});
});
However, running this test results in:
Invariant Violation: <Route> elements are for router configuration only and should not be rendered
I think I understand that the issue might be my use of Enzyme's shallow method. I took this solutions from this SO question. I believe I understand that it is attempting to parse through the wrapper in search of a Route call, putting each into a hashtable and using that to determine if the correct component is in the table where it should be, but this is not working.
I've looked through a lot of documentation, Q&A, and blog posts trying to find "the right way" to test my routes, but I don't feel I'm getting anywhere. Am I way off base in my approach?
React: 15.4.2
React Router: 3.0.2
Enzyme: 2.7.1
Node: 6.11.0
You can't directly render Routes, but a component with Router that uses routes inside. The answer you pointed to has the complete solution.
You will probably also need to change the browserHistory under test environment to use a different history that works on node. Old v3 docs:
https://github.com/ReactTraining/react-router/blob/v3/docs/guides/Histories.md
As a side note, what's the point of testing Route which I assume is already tested in the library itself? Perhaps your test should focus on your route components: do they render what they should based on route params? Those params you can easily mock in your tests because they're just props.
I'm telling you this because in my experience understanding what to test was as important as learning how to test. Hope it helps :)

Resources