I have an application with this config for history:
import { createHashHistory } from 'history';
import { ConnectedRouter } from 'connected-react-router';
const history = createHashHistory({
hashType: 'slash',
});
...
<ConnectedRouter history={history}>
<App />
</ConnectedRouter>
But all my routes get appended by /#
ex: localhost:8080/ becomes: localhost:8080/#/
I already tried to update my packages as this question say but it didn't work.
The only thing that worked was change createHashHistory to createBrowserHistory, but I'm not sure what's the difference between them, and why createHashHistory is appending the /#
With hashHistory, it produces url like
http://yourwebsite.net/#page/xxx
With browserHistory, it produces url like
http://yourwebsite.net/page/xxx
Which one to use? In real-world products, browserHistory is mostly used. A rule of thumb is "if you are using a dynamic server that can handle dynamic URLs then you need to use the BrowserRouter component but if you are using a server that only serves static files then a HashRouter component is what to be used in this case."
In your code, hashType: 'slash' is just the default value.
Related
I'm building a ReactJS website as part of a web dev bootcamp project.
I made a search feature using flask routes between the reactjs endpoints (../Language.js) and my Sqlite3 database.
http://localhost:3000/kanjisearch
How do I make the result of a search into an endpoint itself though? For example if a user searches for "german verbs" the browser displays something along the lines of:
http://localhost:3000/kanjisearch?=german+verbs
I want this so that when users hit the forward or back arrows on the browser, it takes the user to the previous search, NOT the previous page they were on.
Can I do this is react/javascript? Something else?
Thank you.
yes you can, you can use react-router-dom library
just do yarn add react-router-dom and create a route.js file and do the following
import React from "react";
import { BrowserRouter as Router, Switch, Route } from "react-router-dom";
import someScreen from "../somewhere" // this would be your Screen that you wanna show
const Routes = () => {
return (
<Router>
<Switch>
<Route path="/container/language/:language" component={someScreen} />
</Switch>
</Router>
);
};
export default Routes;
after that you have to fix your app.js file as the following
import React from 'react';
import './App.css';
import Routes from './router '; //the location of your router
function App() {
return (
<div className="App">
<header className="App-header">
<Routes/>
</header>
</div>
);
}
export default App;
go to your component and do export default withRouter(someScreen)
In your screen Since you have now a connected Class (to the routing) you can access match inside your props, this props is created by react-router and contains informations about what matched in this route : For exemple match.params.language would contains the :language from the route, meaning if u have /german+verbs
and now you can use the url like http://localhost:3000/container/language/german+verbs and then german+verbs
your parameters would be passed to your component as as
match.params = {
language: 'language+verbs'
}
use this is in your compDidMount method
Well... what language do you want to use? :-) . You can do it in any of those you mentioned.
Since you mentioned ReactJS first, you can do it in javascript by using the window.location object. Just set and read the hash. BTW the hash can be anything and is ignored by the browser, but your JS can look at it. Your url would look something like this:
http://localhost:3000/container/language/Language#search=german+verbs.
I have built authorization into my React App using passport.js, and I would like to, in my App.js file, fetch my authorization routes to see if a user is logged into the app, or if nobody is logged in.
To help with the question, I have shared a condensed version of my React App's App.js file, and Index.js file.
// App.js File
// Import React Libraries, Routes, Container Pages
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { Route } from 'react-router-dom';
import { userActions } from './actions/auth/auth-actions.js';
import GameLanding from './containers/StatsPages/Game/GameLanding';
import AppFooter from './components/AppFooter';
// And Create The App
class App extends Component {
constructor(props, context) {
super(props, context);
}
componentDidMount() {
this.props.dispatch(userActions.authorize());
}
render() {
return (
<div>
<Route exact path='/stats/games' render={() => <GameLanding userInfo={this.props.userInfo} />} />
<AppFooter />
</div>
);
}
}
// export default App;
function mapStateToProps(reduxState) {
return {
userInfo: reduxState.authorizedReducer.userInfo,
authorized: reduxState.authorizedReducer.authorized,
loading: reduxState.authorizedReducer.loading
};
}
export default connect(mapStateToProps)(App);
... my entire App.js file has ~15 Routes components, and (part of) my goal with my App.js file is to fetch the authorized and userInfo props, and pass these to the components in the various routes. I showed an example where I pass the userInfo prop to the GameLanding component.
Here is how I have set up my Index.js file.
// Index.js
// Import Libraries
import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import { BrowserRouter } from 'react-router-dom';
// Import CSS and the App
import App from './App';
import 'react-table/react-table.css';
import './index.css';
import './App.css';
ReactDOM.render(
<Provider store={store}>
<BrowserRouter>
<App />
</BrowserRouter>
</Provider>,
document.getElementById('root'));
My current problem is as such: For some reason, fetching the userInfo and authorized props is breaking my app. I am unfortunately getting no error messages... rather, all of the react-router-dom Links in my app are simply not working... clicking them changes the url, but the pages of my app no longer change...
My questions are then, (a) am i allowed to fetch authorization data in App.js in the manner I am doing so (using connect, with mapStateToProps, etc.), or am I doing this all wrong?
Whether or not somebody is logged into my app is an app-wide thing, not a page-specific thing, and I figured for this reason (also to prevent having to fetch auth props in many many container pages) that App.js is the best place to grab these props.
Any thoughts on why my app is breaking, or how else my App.js file should look (I am ~99% sure my index.js is fine), would be greatly appreciated! Thanks!
Edit: For reference, doing the following: (i) importing userActions, (ii) calling userActions.authorize() in componentDidMount, (iii) including the mapStateToProps and connect on bottom of app, etc. works for loading the auth props in any of my container components. e.g. if i had this code in my GameLanding component, it doesnt break the react-router-dom Links app-wide in the same manner that it does when this code is in App.js. Hence the title of the question. Thanks!
1) Reason for app breaking:
I am assuming userInfo and authorized props will be undefined, as component renders initially before componentDidMount runs and you have not handled undefined props. You could also pass default props for these props.
2) Better structure for authorization
I am assuming you need to authenticate each route for authorization.
i) Create routes file and enter all routes for your app.
ii) <Route exact path='/stats/games' component={GameLanding} onEnter={reqAuth}/>
Inside reqAuth function you should check if the user is authorized for that route or not.
iii) Inside App component call action for fetching data, store in store and use GameLanding as child component and pass props only when they are defined.
That is not whole code, but should give you gist.
Happy Coding!!!
I am creating my first react app in electron (my first electron app too). I have two routes & need to navigate from one to another. For that I am using following code:
Root
ReactDOM.render(
<Router history={browserHistory}>
<App />
</Router>,
document.getElementById('root')
);
App
class App extends React.Component {
constructor() {
super();
}
render() {
return (
<div className="app-master">
<Switch>
<Route path='/city' component={CityList}/>
<Route path='/' component={SplashScreen}/>
</Switch>
</div>
)
}
}
Page
import { browserHistory } from 'react-router';
...
browserHistory.push('/city');
This line gives error,
TypeError: Cannot read property 'push' of undefined
I searched web for possible solution but can't find one! There are many similar questions on SO too, but none of it worked for me :(
You have to import it from the history module now which provides 3 different methods to create different histories.
createBrowserHistory is for use in modern web browsers that support the history API
createMemoryHistory is used as a reference implementation and may also be used in non-DOM environments, like React Native or tests
createHashHistory for legacy web browsers
You cannot use the browser history in an electron environment, use the hash or the memory one.
import { createHashHistory } from 'history'
const history = createHashHistory()
You can then use the history injected in the props
this.props.history.push('/')
Useful pointers above. The simplest solution I've found is to add:
import {createBrowserHistory} from 'history';
to your list of import statements, then add:
const browserHistory = createBrowserHistory();
Might not work perfectly, but for the basic stuff I'm working on seems to do the trick. Hope that helps.
Its is not working for your because in your component you are still using browserHistory which is not longer availabe from react-router package. You should change to using history from the history package
To simplify you can create a history.js file with the following contents
import { createBrowserHistory } from 'history'
export default createBrowserHistory();
Root
import history from '/path/to/history';
ReactDOM.render(
<Router history={history}>
<App />
</Router>,
document.getElementById('root')
);
Page
import history from 'path/to/history';
...
history.push('/city');
import { browserHistory } from 'react-router' does not work in React router 4. Link
Use the redirect component:
import { Redirect } from 'react-router';
<Redirect push to="/somewhere/else"/>
The render function should replace the entire content with Redirect component.
In react-router v4 initialize router as constant config and access the history through this.props in child components.
Import you dependecies
import { Route, Router } from "react-router";
import { createBrowserHistory } from "history";
Define your router config and add history as prop
const history = createBrowserHistory();
const routes = (
<Router history={history}>
<Route path='/city' component={CityList}/>
<Route path='/' component={SplashScreen}/>
</Router> )
class App extends Component {
render() {
return (
<div className = "app-master>
{routes}
</div>)
}
Defining route as a constant and out of render method this would initialize the route config only once.
Page Component
class Page extend Component {
render() {
this.props.history.push('/');
}
}
The history is now available as props in all the child components defined in routes config.
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 want to route to another path in the render function in react-router-1.0.3. I can redirect the user by providing a link using:
render(
<Link to={`/${this.props.params.projectSlug}/`}>
Please follow this link to access your workspace.
</Link>
)
But I cant seem to programmatically forward to this link. I tried:
render(
<Router history={browserHistory} routes=
{`/${this.props.params.projectSlug}/`}/>
)
How can I programmatically forward to a relative path in react-router 1.0.3?
Try upgrade router to the latest version if you don't mind;
Then, they strictly clarify how to do it here.
// Your main file that renders a <Router>:
import { Router, browserHistory } from 'react-router'
import routes from './app/routes'
render(
<Router history={browserHistory} routes={routes} />,
mountNode
)
&
// Somewhere like a Redux middleware or Flux action:
import { browserHistory } from 'react-router'
// Go to /some/path.
browserHistory.push('/some/path')
// Go back to previous location.
browserHistory.goBack()