Resume: I need to run React Router without wepback or similar tools. Directly from CDN links, but I'm stuck with some require.js error.
I'm starting to build my first App with React and I'm struggling with React Router.
HTML:
<body>
<div id="container"></div>
<script src="https://unpkg.com/react#15/dist/react.js"></script>
<script src="https://unpkg.com/react-dom#15/dist/react-dom.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.23/browser.js"></script>
<script src="https://npmcdn.com/react-router#2.4.0/umd/ReactRouter.js"></script>
<script type="text/babel" src="assets/scripts/03_templates/app.js" charset="utf-8"></script>
</body>
JS:
var { Router, Route, IndexRoute, hashHistory, IndexLink, Link, browserHistory } = ReactRouter;
//some classes
ReactDOM.render((
<Router history={hashHistory}>
<Route path="/" component={Window}>
<IndexRoute component={InitialPage}/>
<Route path="register" component={Register} />
<Route path="search" component={Search} />
</Route>
</Router>
), document.getElementById("container"));
Everything is running fine but i get this on console:
react.js:3639 Warning: You are manually calling a React.PropTypes
validation function for the getComponent prop on IndexRoute. This
is deprecated and will not work in production with the next major
version. You may be seeing this warning due to a third-party PropTypes
library.
So, I suppose my react Router is a old version. I changed the link to
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-router/4.0.0-0/react-router.js"></script>
Warning: React.createElement: type should not be null, undefined,
boolean, or number. It should be a string (for DOM elements) or a
ReactClass (for composite components).
I search about it and it seems the problem is on line 1. So I changed this:
var { Router, Route, IndexRoute, hashHistory, IndexLink, Link, browserHistory } = ReactRouter;
To this:
import { Router, Route, IndexRoute, hashHistory, IndexLink, Link, browserHistory } from 'react-router';
And now I have this problem:
app.js:2 Uncaught ReferenceError: require is not defined
I searched for require.js, tried some stuff but nothing fixed my problem. What am I missing? I need to run this without webpack or similars tools.
Thanks
for react route v4.0,please read react-router package
add two js link on your page:
<script src="https://unpkg.com/react-router/umd/react-router.min.js"></script>
<script src="https://unpkg.com/react-router-dom/umd/react-router-dom.min.js"></script>
in js code you can use :
const Router = window.ReactRouterDOM.BrowserRouter;
const Route = window.ReactRouterDOM.Route;
const Link = window.ReactRouterDOM.Link;
const Prompt = window.ReactRouterDOM.Prompt;
const Switch = window.ReactRouterDOM.Switch;
const Redirect = window.ReactRouterDOM.Redirect;
also,can use
console.log(window.ReactRouterDOM);
to out put all object like:
ReactRouteDOM Objects
Here's a minimal example of how this can be accomplished:
<!DOCTYPE html>
<html>
<head>
<meta charset='UTF-8'>
<script src='https://unpkg.com/react#16.3.1/umd/react.production.min.js'></script>
<script src='https://unpkg.com/react-dom#16.3.1/umd/react-dom.production.min.js'></script>
<script src='https://unpkg.com/react-router-dom#5.0.0/umd/react-router-dom.min.js'></script>
<script src='https://unpkg.com/babel-standalone#6.26.0/babel.js'></script>
</head>
<body>
<div id='root'></div>
<script type='text/babel'>
const Link = ReactRouterDOM.Link,
Route = ReactRouterDOM.Route;
const App = props => (
<ReactRouterDOM.HashRouter>
<ul>
<li><Link to="/">TO HOME</Link></li>
<li><Link to="/a">TO A</Link></li>
<li><Link to="/b">TO B</Link></li>
</ul>
<Route path="/" exact component={Home} />
<Route path="/a" component={A} />
<Route path="/b" component={B} />
</ReactRouterDOM.HashRouter>
)
const Home = props => <h1>HOME</h1>
const A = props => <h1>A</h1>
const B = props => <h1>B</h1>
ReactDOM.render(<App />, document.querySelector('#root'));
</script>
</body>
</html>
Use this on top of your javascript:
var Router = ReactRouter.Router;
var Route = ReactRouter.Route;
var IndexRoute = ReactRouter.IndexRoute;
var Link = ReactRouter.Link;
var browserHistory = ReactRouter.browserHistory;
and remove the import statements.
I'm currently using this react-router package: https://unpkg.com/react-router#3.0.0/umd/ReactRouter.js
EDIT:
Here's an example at CodePen: http://codepen.io/lsmoura/pen/pNPOzp -- it uses no import statements.
Related
Method:
onSearch(searchString) {
if (this.props.history) {
this.props.history.push(
"/details?search=" + encodeURIComponent(searchString)
);
}
}
Search Bar:
<Search
onKeyPress={(event) => {
if (event.key === "Enter") {
this.onSearch(event.target.value);
}
}}
/>
onSearch method opens this url: http://localhost:3000/marketPlace/details?search=iphone and surfacing all the results with "iphone". What I want is whenever user bookmark this url, he should fall back in the same page with the search result as iphone . I have no idea how to do this, can anyone help me with this
Assuming you are writing a client side application and you do not need the search results to be server side rendered, React Router (npm react-router-dom) will enable you to recreate a particular state of your app, based upon the url requested.
You should be able to apply a router to your existing app by following the React Router documentation: https://reacttraining.com/react-router/web/guides/quick-start
Here is a very simple example of a router that is similar to your use case.
The example shows that:
A request to / will render the "Homepage" component.
A request to /search?term=iphone will render the "SearchResults" component and this.searchTerm will be equal to the string iphone.
The SearchResults component parses the query string from the url and identifies the search term. In the example, this is just displayed to the end user, but you can use it to fetch your search results e.g. using fetch().
You can reproduce the example with two files:
index.js
import React from 'react';
import ReactDOM from 'react-dom';
import {
BrowserRouter as Router,
Switch,
Route
} from 'react-router-dom';
class SearchResults extends React.Component {
constructor(props) {
super(props);
let queryString = new URLSearchParams(props.location.search);
this.searchTerm = queryString.get('term');
}
render() {
return <p>Search results page for term: { this.searchTerm }</p>;
}
}
function App() {
return (
<Router>
<Switch>
<Route path="/search" component={SearchResults} />
<Route path="/">
<p>Homepage</p>
</Route>
</Switch>
</Router>
);
}
ReactDOM.render(<App />, document.getElementById('root'));
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>React App</title>
</head>
<body>
<div id="root"></div>
<script src="index.js"></script>
</body>
</html>
I want to get the location of the page I'm on in order to set up conditional rendering. Originally, I had something set up like this
const currentPath = window.location.pathname;
...
<h1>{currentPath}</h1>
And that would echo out the path as http://example.com/page.
But since I've switched to using HashRouter, and page links are generated like http://example.com/#/page, the only thing that echoes out is "/"
How do I get the location of the page after the hash?
Route in React-router v4 passes three props to the component it renders. One of these is the match object. It contains information about how the current path was matched.
In your case, you can use match.path or match.url to get the location of the page.
Something like this:
import React from 'react';
import { render } from 'react-dom';
import { Route, HashRouter as Router, Switch } from 'react-router-dom';
const Child = ({ match }) => {
return <p>{match.url}</p>;
};
const App = () => (
<Router>
<Switch>
<Route exact path='/' component={Child} />
<Route exact path='/test1' component={Child} />
<Route exact path='/test2' component={Child} />
</Switch>
</Router>
);
render(<App />, document.getElementById('root'));
Working code is available here:
https://codesandbox.io/s/3xj75z41z1
Change the route in the preview section on the right to / or /test1 or /test2, and you'll see the same path displayed on the page.
Hope this helps. Cheers! :)
React Router provides location parameter out of box.
You can access it like location.pathname
For eg: if the component is Page:
const {HashRouter, Route, Link} = ReactRouterDOM;
function Page({location}) {
return <p>{location.pathname}</p>;
}
class App extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<HashRouter>
<div>
<Route path="/page" component={Page} />
<Link to='/page'>Link to Page</Link>
</div>
</HashRouter>
);
}
}
ReactDOM.render(<App />, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<script src="https://unpkg.com/react-router-dom/umd/react-router.min.js"></script>
<script src="https://unpkg.com/react-router-dom/umd/react-router-dom.min.js"></script>
<div id="root"></div>
https://reacttraining.com/react-router/web/api/location
I have a React Component called ContentBar that holds a Route to display dynamic content:
//ContentBar.js
var React = require('react')
import ContentBarRoute from '../../../../routes/contentbar.routes'
const ContentBar = () =>
(
<ContentBarRoute />
)
export default ContentBar
I've placed this ContentBar in my root App structure:
//App.js
<div className="logBar">
<ErrorBoundary>
<Responsive minWidth={960}>
<ContentBar />
</Responsive>
</ErrorBoundary>
</div>
And I've created a route for a new menu in the ContentBarRoute component which I'm loading in the ContentBar:
//ContactBarRoute.react.js
const ContentBarRoute = () => (
<main>
<Switch>
<Route exact path="/logbar"component={LogBar}/>
<Route path="/user/:number/settings" />
<Route path="/user/:number/profile" />
<Route path="/user/add" component={UserAddMenu} />
</Switch>
</main>
)
When I try to link to /user/add from another component though, I'm not able to update the route from another component:
//Contactlist.react.js
<div className="contact-list useradd">
<Button as={Link} to="/user/add" className="btn-useradd">
<FontAwesome className="icon-adduser" tag="i" name="plus" />
</Button>
</div>
Can someone help me see what I'm doing wrong here? There's not a lot of information about routing between components, I found one answer in my research but it was slightly different: React-Router-4 routing from another component
The problem is that my routes and links are in separate areas of the hierarchy, whereas that guy's components were all close together.
Update:
The other example doesn't talk about rendering new components in place of old ones where one component is totally separate from the other:
Here is my router definition it exists in the class that sends the App to the html div:
import React from 'react'
import { render } from 'react-dom'
import { Provider } from 'react-redux'
//import { createStore } from 'redux'
import { HashRouter } from 'react-router-dom'
import configureStore from '../tools/store.enhancer';
import App from '../javascripts/entry';
//import rootReducer from '../app/reducers/index'
//let store = createStore(rootReducer)
const store = configureStore();
render((
<Provider store={store}>
<HashRouter>
<App />
</HashRouter>
</Provider>
), document.getElementById('root'));
The behavior I expect is that the existing component is switched out for the user-add component, but the actual behavior is that nothing happens when I click the button, and I get an error saying
Hash history cannot PUSH the same path; a new entry will not be added to the history stack
Whenever I try to browse path like "/about" which in browser would be like this : "http://localhost:3000/#/about" . I got my home page. React Router doesn't direct me to wanted path.
I use React Router v4.
This is my App.jsx file :
var React = require('react');
var ReactDOM = require('react-dom');
var Router = require('react-router-dom').BrowserRouter;
var {Route,Link, hashHistory, Switch} = require('react-router-dom');
var Main = require('Main');
var Weather = require('Weather');
var About = require('About');
var Examples = require('Examples');
ReactDOM.render(
<Router>
<div>
<Route exact path="/about" component={About} />
<Route exact path="/examples" component={Examples} />
<Route exact path= "/" component={Main} />
</div>
</Router>
,document.getElementById('app')
);
These 2 solutions didn't work:
React Router Default Route Redirect to /home
React Router always redirect me to a different url
And another question: Which version of React Router is better to use? I think v3 is better than v4,due to simplicity.
You are using a Hash router (as I see in your url). So you have to use HashRouter instead of Router.
var React = require('react');
var ReactDOM = require('react-dom');
var {HashRouter, Route,Link, hashHistory, Switch} = require('react-router-dom');
var Main = require('Main');
var Weather = require('Weather');
var About = require('About');
var Examples = require('Examples');
ReactDOM.render(
<HashRouter>
<div>
<Route exact path="/about" component={About} />
<Route exact path="/examples" component={Examples} />
<Route exact path= "/" component={Main} />
</div>
</HashRouter>
,document.getElementById('app')
);
Wrap you routes with <Switch> component.
Right now, it appears you are using the wrong router. You want to use the HashRouter but you are using the BrowserRouter. Try updating your imports like so.
var React = require('react');
var ReactDOM = require('react-dom');
var { Route, Link, HashRouter as Router, Switch } = require('react-router-dom');
I am trying to use the 1.0.0-rc1 react-router and history 2.0.0-rc1 to navigate manually through the website after pressing the button. Unfortunately, after pressing the button I get:
Cannot read property 'pushState' of undefined
My router code:
import React from 'react';
import { Router, Route, Link, browserHistory } from 'react-router'
import AppContainer from './components/AppContainer.jsx';
import MyTab from './components/test/MyTab.jsx';
import MainTab from './components/test/MainTab.jsx';
var routes = (
<Route component={AppContainer} >
<Route name="maintab" path="/" component={MainTab} />
<Route name="mytab" path="/mytab" component={MyTab} />
</Route>
);
React.render(<Router history={browserHistory}>{routes}</Router>, document.getElementById('main'));
The navigation button is on MyTab and it attemps to navigate to MainTab:
import React from 'react';
import 'datejs';
import History from "history";
export default React.createClass({
mixins: [ History ],
onChange(state) {
this.setState(state);
},
handleClick() {
this.history.pushState(null, `/`)
},
render() {
return (
<div className='container-fluid' >
<button type="button" onClick={this.handleClick.bind(this)}>TEST</button>
</div>
);
}
});
When I use history with this.props.history everything works fine. What is the problem with this code?
EDIT.
After adding the following:
const history = createBrowserHistory();
React.render(<Router history={history}>{routes}</Router>, document.getElementById('main'));
I try to access my app. Before (without history={history}), I just accessed localhost:8080/testapp and everything worked fine - my static resources are generated into dist/testapp directory. Now under this URL I get:
Location "/testapp/" did not match any resources
I tried to use the useBasename function in a following way:
import { useBasename } from 'history'
const history = useBasename(createBrowserHistory)({
basename: '/testapp'
});
React.render(<Router history={history}>{routes}</Router>, document.getElementById('main'));
and the application is back, but again I get the error
Cannot read property 'pushState' of undefined
in the call:
handleClick() {
this.history.pushState(null, `/mytab`)
},
I thougt it may be because of my connect task in gulp, so I have added history-api-fallback to configuration:
settings: {
root: './dist/',
host: 'localhost',
port: 8080,
livereload: {
port: 35929
},
middleware: function(connect, opt){
return [historyApiFallback({})];
}
}
But after adding middleware all I get after accessing a website is:
Cannot GET /
As of "react-router": "^4.1.1", you may try the following:
Use 'this.props.history.push('/new-route')'. Here's a detailed example
1: Index.js
import { BrowserRouter, Route, Switch } from 'react-router-dom';
//more imports here
ReactDOM.render(
<div>
<BrowserRouter>
<Switch>
<Route path='/login' component={LoginScreen} />
<Route path='/' component={WelcomeScreen} />
</Switch>
</BrowserRouter>
</div>, document.querySelector('.container'));
Above, we have used BrowserRouter, Route and Switch from 'react-router-dom'.
So whenever you add a component in the React Router 'Route', that is,
<Route path='/login' component={LoginScreen} />
..then 'React Router' will add a new property named 'history' to this component (LoginScreen, in this case). You can use this history prop to programatically navigate to other rountes.
So now in the LoginScreen component you can navigate like this:
2: LoginScreen:
return (
<div>
<h1> Login </h1>
<form onSubmit={this.formSubmit.bind(this)} >
//your form here
</form>
</div>
);
formSubmit(values) {
// some form handling action
this.props.history.push('/'); //navigating to Welcome Screen
}
Because everything changes like hell in react world here's a version which worked for me at December 2016:
import React from 'react'
import { Router, ReactRouter, Route, IndexRoute, browserHistory } from 'react-router';
var Main = require('../components/Main');
var Home = require('../components/Home');
var Dialogs = require('../components/Dialogs');
var routes = (
<Router history={browserHistory}>
<Route path='/' component={Main}>
<IndexRoute component={Home} />
<Route path='/dialogs' component={Dialogs} />
</Route>
</Router>
);
module.exports = routes
To create browser history you now need to create it from the History package much like you've tried.
import createBrowserHistory from 'history/lib/createBrowserHistory';
and then pass it to the Router like so
<Router history={createBrowserHistory()}>
<Route />
</Router>
The docs explain this perfectly