How to pass flux to react-router 1.0.0 - reactjs

http://fluxxor.com/examples/react-router.html#/
This shows how to do it for the old version of React-router.
Does anyone know how to pass flux as a prop to your top-level component in react-router 1.0.0?
I saw somewhere in the docs that in react-router 1.0.0 routes can just be described as objects and this means you can pass in arbitary props. However this isn't working for me:
routes =
path: "/"
flux: flux
component: App
childRoutes: [
{path: "/path/to/path", component: Comp, flux: flux}
]
React.render(<Router routes={routes} />, document.getElementById("app"))
No sign of flux as a prop on App.
The syntax is Coffee Script but basically routes is an object,

As stated here:
https://github.com/BinaryMuse/fluxxor/issues/137
You can pass a function to the Router createElement property which passes the flux property down to the children components.
const createFluxComponent = (Component, props) => {
return <Component {...props} flux={flux} />;
};
React.render(
<Router createElement={createFluxComponent}>
...

Related

React router 4 history.listen never fires

Switched to router v4 and history v4.5.1 and now history listener not working
import createBrowserHistory from 'history/createBrowserHistory'
const history = createBrowserHistory()
history.listen((location, action) => {
console.log(action, location.pathname, location.state) // <=== Never happens
})
render(
<Provider store={store}>
<Router history={history}>
...
</Router>
</Provider>,
document.getElementById('root')
)
Any ideas why it is being ignored?
Since you are using BrowserRouter(with import alias Router as mentioned in comments of the question), it doesn't care the history prop you pass in. Instead of that it internally creates and assigns new browser history to the Router. So the history instance that you listen and being used in Router is not the same. That's why your listener doesn't work.
Import the original Router.
import { Router } from 'react-router-dom';
It will work as you expect.
The problem is that you are creating your own history object and passing it into the router. However, React Router v4 already provides this object for you, via this.props. (Importing Router has nothing to do with this)
componentDidMount() {
this.props.history.listen((location, action) => console.log('History changed!', location, action));
}
You may need to layer your app a bit more though, like below, and put this componentDidMount method in your MyApp.jsx and not directly at the very top level.
<Provider store={store}>
<BrowserRouter>
<MyApp/>
</BrowserRouter>
</Provider>
(Or use NativeRouter instead of BrowserRouter if you're doing React Native)
works like a magic: 🧙‍♂️🧙‍♂️🧙‍♂️
const history = useHistory();
useEffect(() => {
if (history) { // for jest sake ))
history.listen(() => {
store.reset();
});
}
}, []);

React 0.14.8 doesn't trigger Router's createElement

I'm trying to bump React from 0.13.3 to 0.14.8, but my old setup doesn't work anymore. I've solved all issues very easily, but now I'm stuck and I can't find any hint in the upgrad guide(s).
Here is my setup:
const createElement = (Component, props) => <Component {...props} {...store.getState()}/>
const routes = <Router createElement{createElement} history={browserHistory}><Route>...</Route></Router>;
store.subscribe(() => ReactDOM.render(routes, containerElement));
So basically, everytime the store changes, ReactDOM.render is called and routes is rendered. routes should call createElement on render and did just that in 0.13, but not anymore in 0.14. Only when the route/url changes, the UI is updated with the latest data.
Any idea where the problem is coming from (React, ReactRouter, Redux) and how to debug/fix are most welcome!

How to use React Router properly? I am trying to push the state of my application to another page when the user logs in

After a user successfully logs in, I want to push the state of my application to the '/home' route, which exists and can be accessed by changing the url. The problem is I am getting an error that says
"Cannot read property of push state of undefined"
I am trying to use this.props.history.pushState(null, '/home') to accomplish this reroute to the home page, but obviously this.props.history doesn't exist. Can someone help me use the router correctly?
login.jsx
var Login = React.createClass({
getInitialState: function() {
return {
email: null,
password: null
};
},
handleLogin: function(event) {
event.preventDefault();
var props = {
email: this.state.email,
password: this.state.password
};
axios.post('/login', props).then(() => {
console.log(this.props);
this.props.history.pushState(null, '/home'); //Cannot read property of push state of undefined
});
},
app.jsx contains the route definitions
ReactDOM.render(
<Router history={hashHistory}>
<Route path="/" component={Main}>
<Route path="about" component={About} />
<Route path="home" component={Home} />
<IndexRoute component={Signup} />
</Route>
</Router>,
document.getElementById('masterContainer')
);
It seems that you are not passing the history object as a prop to the Login component - that's where the error comes from (but you probably already know that). So you have to either pass it or use the context. The context seems to be more natural and easy way, but the way it can be used depends on the version of react-router.
If you are using the 2.x version, you will have to add this bit to the component class:
contextTypes: {
router: React.PropTypes.object
},
Then you will be able to use this.context.router.push in your component.
See docs for some info about the methods you can use and this example for more insight.
Edit:
Since the 2.4.0 version you can also use the withRouter component wrapper. In this case you will be able to access router through the props (this.props.router) instead of the context. More info about that here.
For version 1.x you can use the History mixin. Also you should have the history prop on the component that you passed to the router - but since this is not the case, maybe you could just pass it from the parent of the Login component.
The context option is also available (this is how the History mixin works), but this time you will have to pass
contextTypes: {
history: React.PropTypes.object
},
Then you will have all the mixin methods in the this.context.history object.

React update intl dont work: Uncaught ReferenceError: Could not find Intl message:

I did upgrade from react 0.13 to the newest one. Here a list of the dependencies I changed.
react: 0.13.3 -> 0.14.3
react-dom: none -> 0.14.3
react-router: 0.13.3 -> 1.0.3
react-history: none -> 1.0.3
react-intl: 1.2.0 -> 1.2.2
intl: 1.0.0 -> 1.0.1
But I cant get the translations work again.
Uncaught ReferenceError: Could not find Intl message: test
// app.js
var React = require('react');
var ReactDom = require('react-dom');
var Router = require('react-router').Router;
var routes = require('./routes');
var createHistory = require('history').createHistory;
var intlData = {
locales: 'en',
messages: {
test: 'Test'
}
};
ReactDom.render(<Router history={createHistory()} intl={intlData}>{routes}</Router>, document.getElementById('app'));
// Test.js
var React = require('react');
var ReactIntl = require('react-intl');
var IntlMixin = ReactIntl.IntlMixin;
var Test = React.createClass({
mixins: [IntlMixin],
render: function() {
return (
<div>
<h1>
{this.getIntlMessage('test')}
</h1>
</div>
);
}
});
module.exports = Test;
What did I miss in the update? What is the correct way to init my messages.
IntlMixin works by looking on the context for the relevant data, specifically, this.context.locales, this.context.formats, and this.context.messages. It was probably the React Router upgrade from 0.x to 1.x — which changed the way the top-level component is handled — that broke things.
However, if you look at the source linked above, you can see that the mixin looks for the data on this.context only if it's not found on this.props. Thus, if you could pass your internationalization data to every route handler as a prop, things would work fine. Luckily, React Router allows you to do just that via createElement.
createElement should be a function that takes two arguments: the component React Router wants to render, and the props it wants to send it. The function should render that component with the given props. The default implementation looks like this:
function createElement(Component, props) {
return <Component {...props} />
}
However, you can further customize how the component gets rendered. For your case, it might look something like:
function createIntlElement(Component, props) {
return <Component intl={intlData} {...props} />
}
although it looks like from the React Intl docs that the props should be split out, so if that doesn't work, maybe more like:
function createIntlElement(Component, props) {
return <Component {...props}
locales={intlData.locales}
messages={intlData.messages} />
}
or, more simply using the spread syntax,
function createIntlElement(Component, props) {
return <Component {...props} {...intlData} />
}
You then instruct the router to use your createElement function by passing it to the createElement prop:
var router = (
<Router history={createHistory()} createElement={createIntlElement}>
{routes}
</Router>
);
ReactDom.render(router, document.getElementById('app'));
Don't forget to include IntlMixin on all your route handlers so that child components that aren't directly rendered by the router still have access to the context.
React Intl version 2 (now in beta) appears to use a IntlProvider component, much like Redux's Provider component, to provide the correct context for you, so using createElement should not be necessary when using that version.

Automatic redirect after login with react-router

I wanted to build a Facebook login into my react/react-router/flux application.
I have a listener registered on the login event and would like to redirect the user to '/dashboard' if they are logged in. How can I do that? location.push didn't work very well, except after reloading the page completely.
React Router v3
This is what I do
var Router = require('react-router');
Router.browserHistory.push('/somepath');
React Router v4
Now we can use the <Redirect>component in React Router v4.
Rendering a <Redirect> will navigate to a new location. The new location will override the current location in the history stack, like server-side redirects.
import React, { Component } from 'react';
import { Redirect } from 'react-router';
export default class LoginComponent extends Component {
render(){
if(this.state.isLoggedIn === true){
return (<Redirect to="/your/redirect/page" />);
}else{
return (<div>Login Please</div>);
}
}
}
Documentation https://reacttraining.com/react-router/web/api/Redirect
React Router v0.13
The Router instance returned from Router.create can be passed around (or, if inside a React component, you can get it from the context object), and contains methods like transitionTo that you can use to transition to a new route.
React Router v2
Even though the question is already answered, I think it's relevant to post the solution that worked for me, since it wasn't covered in any of the solutions given here.
First, I'm using the router context on my LoginForm component
LoginForm.contextTypes = {
router: React.PropTypes.object
};
After that, I can access the router object inside my LoginForm component
handleLogin() {
this.context.router.push('/anotherroute');
}
PS: working on React-router version 2.6.0
React Router v3
Navigating Outside of Components
create your app with Router like this
// 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()
react-router/tree/v3/docs
React Router v4.2.0
I am using React-16.2.0 & React-router-4.2.0
And I get solution by this code
this.props.history.push("/");
My working code:
.then(response => response.json())
.then(data => {
if(data.status == 200){
this.props.history.push("/");
console.log('Successfully Login');
}
})
I was following this document redirect-on-login-and-logout
I was also try by return <Redirect to='/' /> But unlucky, this not working for me.
React router v5 using hooks
These steps are for authorisation redirect. But can be used for login/logout redirection also.
The <Redirect/> accepts to prop as a string or an object. We can utilise the object to pass the redirection path after login/logout using hooks easily.
Get the pathname of url from where the <Redirect/> is called using
useLocation()
const {pathname} = useLocation()
In the to prop of <Redirect/> pass in the following object:
<Redirect to={{pathname:'/login',state: {referrer: pathname}}/>
In the Login component access the route state variable using useLocation() hook and use the useHistory() hook to redirect after successful login.
const history = useHistory();
const location = useLocation();
const login() => {
// After login success
const {state: {referrer}} = location;
history.push(referrer)
};
Check the official docs here
React Router v3
Navigating inside components
You should use withRouter decorator when it's necessary to redirect inside a component. The decorator uses context instead of you.
import {withRouter} from 'react-router'
fucntion Foo(props) {
props.router.push('/users/16');
}
export default withRouter(Foo);
withRouter(Component, [options])
A HoC (higher-order component) that wraps another component to enhance
its props with router props.
withRouterProps = {
...componentProps,
router,
params,
location,
routes
}
Pass in your component and it will return the
wrapped component.
You can explicit specify router as a prop to the wrapper component to
override the router object from context.
In your store:
data.router.transitionTo('user');
And router has:
"Route name="user" handler={User}"
User is route handler

Resources