人ã ã¯ãç§ãã¡ãReact RouterããµããŒãããŠããªãããŸãã¯ãããæ©èœããããã«redux-react-routerã®ãããªç¹å¥ãªãã®ãå¿ èŠã§ããããããã¯React0.14ãŸã§æ©èœããªããšããå°è±¡ãåžžã«åãââãŸãã
çŸåšã®ããã«ãReact Router0.13ãŸãã¯1.0ã§Reduxã䜿çšã§ããŸãã
ïŒã¡ãªã¿ã«ãReduxã®æåã®ãªãªãŒã¹ä»¥æ¥ãããã¯çå®ã§ãããïŒ
ã¿ã€ã ãã©ãã«ãªã©ã®äžéšã®æ©èœã¯ãRRåŽã§ã®ãµããŒããåŸ ã€å¿ èŠããããŸãããããã¯äž»èŠãªåé¡ãšã¯ç¡é¢ä¿ã§ãã ä»æ¥ã¯ã«ãŒãã£ã³ã°ã䜿çšã§ããªããšäººã ã¯æ··ä¹±ããŸãããããã¯ééã£ãŠããŸãã
ãã®ãªããžããªã«å«ãŸããŠããå®éã®äŸã§ã¯ãReactRouterã䜿çšããŠããŸãã å¿
èŠãªã®ã¯ãã«ãŒã¿ãŒã®ãªãã¢ããªã§æäžäœã®ã³ã³ããŒãã³ããã©ããããã®ãšåãããã«ã <Router>
ã<Provider>
ã«ã©ããããããšã§ãã
ã¢ã¯ã·ã§ã³ã¯ãªãšãŒã¿ãŒãã移è¡ããå Žåã¯ã router
ã€ã³ã¹ã¿ã³ã¹ããã©ã¡ãŒã¿ãŒãšããŠã¢ã¯ã·ã§ã³ã¯ãªãšãŒã¿ãŒã«æž¡ããå¿
èŠã«å¿ããŠãã®ã¡ãœãããåŒã³åºããŸãã Reduxã¹ãã¢ããã«ãŒã¿ãŒã®ç¶æ
ãèªã¿åãããå Žåã¯ãã«ãŒãå€æŽæã«ã¢ã¯ã·ã§ã³ãå®è¡ãããããåŠçããããã®ã¬ãã¥ãŒãµãŒãäœæããŸãã ããã§ãããŸãïŒ
react-redux-routerã¯ãã¢ã¯ã·ã§ã³ããã£ã¹ãããããã«ãŒã¿ãŒã€ã³ã¹ã¿ã³ã¹ã«èªåçã«æ¥ç¶ãããŠããã¹ãã¢ããç¶æ ãèªã¿åããããèªç¶ãªAPIãèãåºãããã®å®éšã§ãããããã䜿çšããå¿ èŠã¯ãããŸãããå®å®ããã®ãåŸ ã€ïŒ ããã¯å®éšã®ã¿ã§ãã
ããã¯ããã¥ã¡ã³ãã§å¿ èŠã§ãã
ç§ã¯ããšããšããŠãããŒãµã«ã³ã³ããã¹ãã§reactã«ãŒã¿ãŒã䜿çšããããã®ãµãŒããŒåŽã¬ã³ããªã³ã°ã®äŸãäœæããŸããã åå¿ã«ãŒã¿ãŒã§ã®äœ¿çšã¯ããèªèº«ã®ææžã«ãªãå¯èœæ§ãããããšã瀺åãããŸããã ãããããããã¥ã¡ã³ãã«ã»ã¯ã·ã§ã³ãè¿œå ã§ããŸããïŒ
ãŸããreactã«ãŒã¿ãŒãåºã䜿ãããŠããããšã瀺ãäŸãè¿œå ããããšã«ã€ããŠã©ãæããŸããïŒ
real-world
ã®äŸããŠãããŒãµã«ã«å€æŽããã®ã¯è¯ãèãã ãšæããŸãã ããããã°ãæåããäœãäœæããå¿
èŠããããŸããã
ã¢ã¯ã·ã§ã³ã¯ãªãšãŒã¿ãŒãã移è¡ããå Žåã¯ãã«ãŒã¿ãŒã€ã³ã¹ã¿ã³ã¹ããã©ã¡ãŒã¿ãŒãšããŠã¢ã¯ã·ã§ã³ã¯ãªãšãŒã¿ãŒã«æž¡ããŸã
æ確ã«ãããã£ãã®ã§ããã1.0betaã«ã¯createRouter
ã®æŠå¿µããªããããããã¯0.13ã§ã®ã¿æ©èœããŸãïŒãŸã ïŒïŒãæ£ããã§ããïŒ
Reactã³ã³ããŒãã³ãå ãã1.0.0-beta3ã§ãããè¡ãããšãã§ããŸãã
class Thing extends Component {
static contextTypes = {
router: PropTypes.object
}
handleThing() {
this.props.actionCreator(this.context.router);
}
}
@timdorr this.context
ã䜿çšããŠãå®å
šã§ããïŒ ç§ã¯ãããå€éšã§äœ¿çšãããããšãæå³ãããŠããªãã£ããšããå°è±¡ãåããŸããã
ã¯ããããã¯ææžåãããŠããªãã ãã§ãå®å šã§ã¯ãããŸããã 0.14ã§ãããã«å€æŽãããŠããŸããããããå£ããããªæ¹æ³ã§ã¯ãããŸããã è¿ããã¡ã«ææžåããããšæããŸãã
@timdorrããã¯ã1.0.0-beta3ã®ã¢ã¯ã·ã§ã³ã¯ãªãšãŒã¿ãŒãšã¯ç°ãªãURLã«ç§»è¡ã§ããããšãæå³ããŸããïŒ
ã¯ããã«ãŒã¿ãŒã€ã³ã¹ã¿ã³ã¹ãã¢ã¯ã·ã§ã³ã¯ãªãšãŒã¿ãŒã«æž¡ããšããã©ã³ãžã·ã§ã³ãå«ããã«ãŒã¿ãŒã€ã³ã¹ã¿ã³ã¹ã䜿ã£ãŠå¥œããªããšãè¡ãããšãã§ããŸãã
ç§ã¯ãããäžç·ã«æããŸããïŒ
const loginProps = {
handleLogin: ({email, password}) => store.dispatch(userLogin({email, password})),
};
const routes = (
<Route path="/" handler={App}>
<Route path="login" handler={wrapper(Login, loginProps)} />
<Route handler={authSection}>
<Route path="" handler={Index} />
<Route path="users" handler={wrapper(Users, (() => store.dispatch(getUsers())))} />
<Route path="logout" handler={wrapper(Login, (() => store.dispatch(userLogout())))} />
</Route>
</Route>
);
const router = createRouter({
location: HistoryLocation,
routes,
});
store.dispatch(receiveRouter({router}));
Warning: Failed Context Types: Required context `store` was not specified in `SmartComponent(TodoApp)`. Check the render method of `Router`.
äœãåé¡ãªã®ã§ããïŒ
PSïŒRR 1.0.0-beta3
@gyzerok real-world
ã®äŸãšåãããã«ã () => <Router>stuff</Router>
å
šäœã$ïŒ <Provider>
ã«ã©ããããããã«ããŠãã ããã
@gaearonã¯ããofcã ç§ã¯ããããããã€ããŒã§ã¯ãªããããªãã®ãããã€ããŒã®ã³ããŒïŒããŒã¹ãã§ããç§èªèº«ã®ã³ã³ããŒãã³ãã§ã©ããããŸãã éãã¯ãã¹ãã¢ãæž¡ãã®ã§ã¯ãªãããã®äžã«ã¹ãã¢ãäœæããããšã§ãã
@gyzerokã³ãŒããèŠãã«äœãæªãã®ããèšãã®ã¯é£ããã§ãã ïŒãããŠãå¥ã®åé¡ãæåºããŠãã ããreact-redux
ãªããžããªã¯è¯ãå Žæã§ããïŒ
real-wolrd
ã®äŸã®ThxïŒ ãããã AsyncProps
ãã©ã®ããã«åŠçããã®ã§ããïŒ ããã«ã³ã³ããã¹ãæäœã¯äžç·ã«æ©èœããªãããã§ãã
import React from 'react';
import {createStore} from 'redux';
import {Provider} from 'react-redux';
import {Router, Route} from 'react-router';
import BrowserHistory from 'react-router/lib/BrowserHistory';
import AsyncProps from 'react-router/lib/experimental/AsyncProps';
import App from './containers/App';
import reducers from './reducers';
const store = createStoreWithMiddleware(reducers);
const history = new BrowserHistory();
React.render(
<Provider store={store}>
{() =>
<Router history={history} createElement={AsyncProps.createElement}>
<Route component={AsyncProps}>
<Route path="/" component={App} />
</Route>
</Router>
}
</Provider>,
document.body
);
ããã³App.js
import React from 'react';
import {connect} from 'react-redux';
let App = React.createClass({
statics: {
loadProps(params, cb) {
// have to call this with AsyncProps
}
},
displayName: 'App',
render() {
return <div children="this is app" />
}
});
export default connect(state => state)(App);
connect
ã©ãããŒããªããŠãæ©èœããŸããã redux
ããããŸããã 誰ãããã®åé¡ã«çŽé¢ããŸãããïŒ
ãŸãã¯ãããŒã¿ãèªã¿èŸŒãŸãããŸã§ããã²ãŒã·ã§ã³ãäžæåæ¢ããä»ã®æ¹æ³ã¯ãããŸããïŒ
éååŠã¯åãªãéååŠã§ãã connect()
ã®çµæãå«ããäœã«ã§ã眮ãããšãã§ããŸãã
let App = React.createClass({
displayName: 'App',
render() {
return <div children="this is app" />
}
});
App = connect(state => state)(App);
App.loadProps = function loadProps(params, cb) {
// have to call this with AsyncProps
}
export default App;
@gaearonç³ãèš³ãããŸããããäŸããã£ã±ãã§ã¯ãããŸããã éçãªå°éå
·ããªãç¶æ
ã§connect
ã®çµæãæ¡åŒµããããšããŸããããã³ã³ããã¹ãã«å®éã®åé¡ããããŸãã ãã°ãããåŸ
ã¡ãã ãããäŸå
šäœãå¥ã®ãªããžããªã«ããã·ã¥ããŸã
ç§ãçŸåšèª¿æ»ããŠãããã1ã€ã®ããšã¯ããã©ã¡ãŒã¿ãŒãæ確ã§ç®ç«ããªãæ¹æ³ã§reduxã¹ãã¢ã«ä¿åããããšã§ãã ããã€ãã®ã¢ãããŒããè©ŠããåŸãç§ã¯æçµçã«æ¬¡ã®ããã«æžããŸããã
<Route
component={OrderDetails}
path='/orders/:orderId'
onEnter={({params}) => store.dispatch(setCurrentOrder(params.orderId))}
/>
ãããã£ãŠã以äžã®ããã«ãã»ã¬ã¯ã¿ãŒãããã©ã¡ãŒã¿ãŒãåç §ããããšãã§ããŸãã
export const OrderDetails = state => {
const {order} = state;
return {
order: order.details.get(order.currentOrderId),
orderId: order.currentOrderId,
isLoading: order.isLoadingDetails,
error: order.detailsLoadingError
};
};
ããå®å®ããreact-redux-router
ããªãªãŒã¹ããããšãããããå€æŽãããŸãã
æå ±ïŒReact Router 1.0 RCã¯ãå¿
èŠãªããã¯ãå
¬éããããã«ãªããŸããã
https://github.com/acdlite/redux-react-routerããã§ãã¯ããŠãä»ããæ°ã«å
¥ã£ããã©ããããç¥ãããã ããã
@gaearon react-router
ãšå®éšçãªAsyncProps
ã®åé¡ãèŠã€ããŸããã åå¿ãæŽæ°ãããšåé¡ã解決ããŸã
@wtfilç¥ã£ãŠãããšè¯ãïŒ
react-routerãšçµ±åãããšãããã®ã¹ã¬ãããããã«ãŒã¿ãŒã€ã³ã¹ã¿ã³ã¹ãã¢ã¯ã·ã§ã³ã¯ãªãšãŒã¿ãŒã«æž¡ãããã®ã¡ãœãããåŒã³åºãããšãã§ããããšãç解ããŠããŸãã ãã ããã¢ã¯ã·ã§ã³ã¯ãªãšãŒã¿ãŒã¯ãæãçŽç²ãªåœ¢ã§å¯äœçšãçºçããªãããã«æå³ãããŠããããšãç解ããŠããŸãã ã¢ã¯ã·ã§ã³ã¯ãªãšãŒã¿ãŒãå¯äœçšãèµ·ããããšãèš±ãããŠããã®ã¯ãããã«ãŠã§ã¢ã«ãã£ãŠåŠçãããéåæã¢ã¯ã·ã§ã³ã®å Žåã ãã§ãã ã§ã¯ãé·ç§»ãå®è¡ããã¢ã¯ã·ã§ã³ã¯ãªãšãŒã¿ãŒã¯çŽç²é¢æ°ã§ã¯ãªãéåæã§ããããšãæåŸ ãããŠããã®ã§ããããã
ã§ã¯ãé·ç§»ãå®è¡ããã¢ã¯ã·ã§ã³ã¯ãªãšãŒã¿ãŒã¯çŽç²é¢æ°ã§ã¯ãªãéåæã§ããããšãæåŸ ãããŠããã®ã§ããããã
ã¢ã¯ã·ã§ã³ã®äœæè ã¯å¯äœçšãæã€ããšãèš±å¯ãããŠããŸãã å¯èœãªéãããããé¿ããã®ãæåã§ããããã¡ããããæç¹ã§ããããå¿ èŠã«ãªããŸããã¬ãã¥ãŒãµãŒã¯Reduxã§çŽç²ã§ãããElmã®ãããªæ瀺çãªãšãã§ã¯ãã¡ã«ããºã ããªãããïŒèª¬æã«ã€ããŠã¯ïŒ569ãåç §ïŒãã¢ã¯ã·ã§ã³ã¯ãªãšãŒã¿ãŒã¯ãããã眮ãå Žæã
redux-routerããã§ãã¯ããŠãã ããã React Routeräžã§åäœããŸãããã¢ã¯ã·ã§ã³ããã£ã¹ãããããã«ãŒã¿ãŒã®åæãåŠçã§ããŸãã
Reactã«ãŒã¿ãŒãšReduxã«ãŒã¿ãŒã®äž¡æ¹ã1.0ã«éããã®ãåŸ ã£ãŠããŸã...
ããã ãããçºçããåŸãã¬ã·ããè¿œå ããŸãã
ã ããç§ã¯ãã®è°è«ã«åŸããã«ãŒãã£ã³ã°ãäžè¬çã«reduxã«ã©ã®ããã«é©åãããã«ã€ããŠãå°ãèããŠããŸãïŒhttps://github.com/rackt/redux/issues/805ãåç §ïŒã ãã®ã¹ã¬ããã§ã®ããã€ãã®è°è«ãšããã€ãã®å®éšã«åºã¥ããŠãç§ã¯react-router / react-redux-routeræ¥çå€ãããå人çã«å¥œãã¢ãããŒããèŠã€ããŸããã
åºæ¬çã«ãç§ã¯react-routerãreduxã«ãäºãã®ç¥èãäžããã代ããã«ã«ã¹ã¿ã å±¥æŽã®å®è£ ãä»ããŠããããæ¥ç¶ããããšããŸãã ãã®ã¢ãããŒãã§ã¯ãã«ãŒãã£ã³ã°ã¯æ¬¡ã®ããã«åŠçãããŸãã
route
ã«å¯ŸããŠãã¹ãã¢å
ã®ã¢ã¯ã·ã§ã³ãã¬ãã¥ãŒãµãŒãããã³ããŒãäœæãããŸããcreateHistory
ã䜿çšããŸããã createHashHistory
ãªã©ãç°¡åã«äœ¿çšã§ããŸãïŒãäœæããããªãã¹ã³ãããŸãã ãã©ãŠã¶ã®çŸåšã®å Žæãå€æŽããããšãROUTEã¢ã¯ã·ã§ã³ããã£ã¹ããããããæçµçã«ãã®å Žæãã¹ãã¢ã«é
眮ãããŸããroute
ããŒãå€æŽããããšãã«ãµãã¹ã¯ã©ã€ããŒïŒreact-routerïŒã«éç¥ãã2çªç®ã®ã«ã¹ã¿ã å±¥æŽå®è£
ã䜿çšããŠäœæãããŸãã ãŸãã createHref
ãšpushState
ãå®çŸ©ããäž¡æ¹ãæé 2ã§äœæããæšæºã®å±¥æŽã«å§ä»»ããŸããããã§ãããŸãã ããã«ãããreduxãšreact-routerã®éã®è·åãããªãæ確ã«åé¢ãããå¥ã®ãæ¥çå€ãã©ã€ãã©ãªãŒãåã蟌ãå¿ èŠããªããªããšæããŸãã 以äžã«ã³ãŒãã貌ãä»ããŠããŸãããã£ãŒãããã¯ãèãããšã«éåžžã«èå³ããããŸãã
// please pay attention to library versions, this strategy is only tested with the indicated versions
import React from 'react'; // v0.13.3
import { Provider } from 'react-redux'; // v3.1.0
import { Router, Route, IndexRoute, Link } from 'react-router'; // v1.0.0-rc3
import { createHistory } from 'history'; // v1.12.3
import { createStore } from 'redux'; // v3.0.2
// define some components
class About extends React.Component {
render () {
return (
<div><h1>About</h1></div>
)
}
}
class Home extends React.Component {
render () {
return (
<div>
<h1>Home</h1>
<Link to="/about">Go to about</Link>
</div>
)
}
}
// create a standard history object
var history = createHistory();
// set up 'route' action and action creator
const ROUTE = 'ROUTE';
function createRouteAction (location) {
return {
type: ROUTE,
payload: location
};
}
// set up reducer. here we only define behavior for the route action
function reducer (state = {}, action) {
if (action.type === ROUTE) {
return Object.assign({}, state, {
route: action.payload
});
}
else {
return state;
// whatever other logic you need
}
}
// create store
const store = createStore(reducer);
// this factory returns a history implementation which reads the current state
// from the redux store and delegates push state to a different history.
function createStoreHistory () {
return {
listen: function (callback) {
// subscribe to the redux store. when `route` changes, notify the listener
const unsubscribe = store.subscribe(function () {
const route = store.getState().route;
callback(route);
});
return unsubscribe;
},
createHref: history.createHref,
pushState: history.pushState
}
}
React.render(
<Provider store={store}>
{() =>
<Router history={createStoreHistory()}>
<Route path="/about" component={About} />
<Route path="/" component={Home} />
</Router>
}
</Provider>,
document.getElementById('root') // or whatever
);
// when the url changes, dispatch a route action. this is placed at the bottom so that the first route triggers the initial render
const unlisten = history.listen(function (location) {
store.dispatch(createRouteAction(location));
});
ã¡ãªã¿ã«ããã®äŸã¯ãreduxã§react-routerã®äœ¿çšã«èŠåŽããŠããç§ã®ãããªäžéšã®äººã ãå©ããreduxãšreact-routerãä»æ¥äžç·ã«äœ¿çšã§ãããšããããªãã®äž»åŒµãæ確ã«ããã®ã«åœ¹ç«ã€ãšæãã®ã§ãããã«ã€ããŠèšåããŸãã
@cappslockç§ã¯ããã奜ãã§ããã1ã€å°ããªããšããããŸãã ããªãã®å®è£
ã§ã¯ãã«ãŒãã®å€æŽã¯ã¢ã¯ã·ã§ã³ã§ãããããã¯ãã¢ã¯ã·ã§ã³ã¯ã³ãã³ãã§ã¯ãªãã€ãã³ãã§ããããšããã¢ãããŒããç Žããæçµçã«ã¯åä»ãªæ
£è¡ã«ã€ãªããå¯èœæ§ããããŸãã èãæ¹ãéã«ããŸããããã¢ã¯ã·ã§ã³ã«ãã£ãŠãã¢ãã¬ã¹ããŒãå€æŽããå¯äœçšïŒã³ã³ããŒãã³ããŸãã¯å®éã®ãã©ãŠã¶ãŒã®ã¢ãã¬ã¹ããŒãªã©ïŒãçºçããå¯èœæ§ãããããã®å¯äœçšã«ãã£ãŠæ°ããã¢ã¯ã·ã§ã³ïŒ ROUTE_CHANGED
ïŒããã£ã¹ããããããå¯èœæ§ããããŸãã ããã¯åºæ¬çã«ãAPIåŒã³åºããããªã¬ãŒããã®ãšåããã¿ãŒã³ã§ãã
@ tomkis1ãã£ãŒãããã¯ãããããšãã ç§ãããªããæ£ããç解ããŠããã°ãããã¯å®éã«ã¯ãã§ã«ãã®ããã«æ©èœããŠããŸãã ROUTE
ã¢ã¯ã·ã§ã³ã¯ãURLå€æŽã®å¯äœçšãšããŠãã£ã¹ããããããŸãã ãã¶ãROUTE_CHANGED
ã®æ¹ãããååã§ããããïŒ
ããŒïŒ ç§ã¯ã¡ããã©ããã«ãã§ãã¯ããŸããããããŠããªãã¯æ£ããã£ãã§ãã ããROUTE_CHANGED
ã®æ¹ãçã«ããªã£ãŠããŸãã
ç§ãããæããŸãã ç§ã¯æ»ã£ãŠãããå€æŽããŸããããããã®ã³ã¡ã³ãã¯æ¬åœã«æ··ä¹±ããã§ããã:)
æ確ã«ããããã«ããããŒã¯æ¬¡ã®ããã«ãªããŸãã
URLã®å€æŽ-> ROUTE
ïŒãŸãã¯ROUTE_CHANGED
ïŒã¢ã¯ã·ã§ã³->ã¬ãã¥ãŒãµãŒæŽæ°ã¹ãã¢->ã¹ãã¢å±¥æŽïŒä»¥åã«ã¹ãã¢ã«ãµãã¹ã¯ã©ã€ããããŠããïŒããªã¹ããŒã«éç¥->ãªã¢ã¯ã·ã§ã³ã«ãŒã¿ãŒã®æŽæ°
ãŠãŒã¶ãŒãç£èŠããUIã®ç¶æ ãé§åããã¹ãã¢ä»¥å€ã¯å¿ èŠãªããããããã奜ãã§ãã ãã¹ãã«ãé©ããŠããããã§ãã
ãã®ã¢ãããŒãã®æ¬ ç¹ã¯ã ROUTE_CHANGED
ã¢ã¯ã·ã§ã³ã«å¿çããŠURLãæŽæ°ãããªãããšã§ãã ã¢ã¯ã·ã§ã³ãã³ãã³ããšããŠæ±ããããªããšèšã£ãŠããå ŽåããããæãŸãããã©ããããããããŸãããã ROUTE_CHANGED
ã¢ã¯ã·ã§ã³äœæè
ã®å¯äœçšãšããŠããŸãã¯ã«ãã£ãŠå®äºããå¯èœæ§ããããšæããŸãå¥ã®ã¹ãã¢ãµãã¹ã¯ã©ã€ããŒã
ãšããã§ããã®è°è«ããã®åé¡ã®ç¯å²ãè¶ ããŠããå Žåã¯ãç§ã«ç¥ãããŠãã ããããããŠç§ã¯ãããåãããŸãã
@cappslockç§ã¯ããããšãŠã奜ãã§ãïŒ ROUTE_CHANGED
ããã£ã¹ãããããŠãã«ãŒããå€ãããªãã®ã¯ééããªããšæããŸãã ã¢ã¯ã·ã§ã³ãããªã¬ãŒã§ã¯ãªãã€ãã³ããšããŠæ±ãããšã¯ãç§ã«ã¯ããã¯ãªãŒã³ã§ç解ããããããã«èŠããŸãïŒãŠãŒã¶ãŒã®æäœã«å¿çããããã BUTTON_CLICKED
ã¢ã¯ã·ã§ã³ãå®éã«ãã¿ã³ã®ã¯ãªãã¯ãããªã¬ãŒããããšã¯æåŸ
ã§ããŸããïŒã ç§ãåŸãããªãããªãã®ã³ãŒãã®äžéšããããŸãã ãã®ãããã«ã€ããŠè©³ãã説æããŠããã ããŸããïŒ
ããã¯ãæåã®ã«ãŒããæåã®ã¬ã³ããªã³ã°ãããªã¬ãŒããããã«äžéšã«é 眮ãããŸã
@elliotdickisonããããšãããããŸãïŒ ãããæ確ã«ããããšæããŸããã培åºçãªåæã§ã¯ãªããè©Šè¡é¯èª€ãšä»®å®ã«åºã¥ããŠããã®ã§ãç§ãèšã£ãŠããããšãäžç²ã®å¡©ã§ãšã£ãŠãã ããã ããã¯ãçŸæç¹ã§ã®æŠå¿µå®èšŒ/ã¹ã±ããã®èšŒæã§ãã
ãã®ã³ãŒããReactRouter
ã®ã€ã³ã¹ã¿ã³ã¹åã®äžã«é
眮ãããšãã /
ã«ãŒãã«å¯Ÿå¿ããã³ã³ããŒãã³ãã¯ã¬ã³ããªã³ã°ãããŸããã§ããã ã¢ã¯ã·ã§ã³ãæåã§ãã£ã¹ããããããå ŽåããŸãã¯ç¶æ
ãæåã§ããã·ã¥ãããå Žåã§ãã«ãŒã¿ãŒã¯æ©èœãããããå±¥æŽã®ã©ã€ããµã€ã¯ã«ã®åé¡ã§ãããšèããŸããã ReactRouter
ã®ã€ã³ã¹ã¿ã³ã¹åã®äžã«ç§»åãããšãããã解決ããŸããã å°ãªããšã1人ã®ãµãã¹ã¯ã©ã€ããŒãååšãããŸã§ãå±¥æŽã©ã€ãã©ãªã¯æåã®ã«ãŒãã®éç¥ã延æããŠãããšæãããŸãã ReactRouterãèšå®ãããåã«ãã®ãµãã¹ã¯ã©ã€ããŒãèšå®ãããŠããå Žåãã©ã®éç¥ãããã«å°éããŸããã
ããã説æããããšãããšãç§ã®ç解ãå°ãæ¬ ããŠããããšã«æ°ã¥ããŸãã ç§ã¯ããããã£ãšèª¿ã¹ãŠãããè¯ãçããæäŸããããšããŸãã
ãã®ã¢ãããŒãã®æ¬ ç¹ã¯ãROUTE_CHANGEDã¢ã¯ã·ã§ã³ã«å¿çããŠURLãæŽæ°ãããªãããšã§ãã ã¢ã¯ã·ã§ã³ãã³ãã³ããšããŠæ±ããããªããšèšã£ãŠããå ŽåããããæãŸãããã©ããããããããŸããããROUTE_CHANGEDã¢ã¯ã·ã§ã³äœæè ã®å¯äœçšãšããŠããŸãã¯å¥ã®ã¹ãã¢ãµãã¹ã¯ã©ã€ããŒã«ãã£ãŠå®äºããå¯èœæ§ããããšæããŸãã
ããã¯æãŸããããšã ãšæããŸãã ROUTE_CHANGED
ã¯ééããªãå€éšãœãŒã¹ïŒonhashchangeãªã©ïŒã«ãã£ãŠèµ·åãããå¿
èŠããããŸããIMOURLãå€æŽãããšã ROUTE_CHANGED
ã«ãªããŸãããã®éã¯ãããŸããã
åæããŸãã ãã£ã¹ããããããROUTE_CHANGED
ã¢ã¯ã·ã§ã³ãå®éã®å±¥æŽã€ãã³ãã§ã¯ãªãã³ãŒãããçºçããå Žåã«åããŠãã¹ãã¢ã«ãµãã¹ã¯ã©ã€ãããURLã®åæãç¶æããã ãã§ãããšæããŸãããããã®å Žåã¯ããã°ã©ãã³ã°ãšã©ãŒã
@cappslockããªãã®ã¢ãããŒãã¯æ¬åœã«è¯ãã§ãã ããã«ã€ããŠããã°æçš¿ããé¡ãããŸãã
@vojtatrantahttps ïŒ//github.com/rackt/redux/issues/805ããã§ãã¯ããŠãã ãããå®è£ ã®èåŸã«ããã€ã³ã¹ãã¬ãŒã·ã§ã³ã ã£ããšæããŸãã
@vojtatrantaããããšãïŒ ç§ã¯ããã°ãæã£ãŠããªãã®ã§ãç§ãæã£ãŠããã»ãšãã©ãã¹ãŠã®æ å ±ã¯ãã®ã¹ã¬ãããšïŒ805ã«ãããŸãã ç¹ã«äœããã£ãšæ å ±ã欲ããã§ããïŒ
1.0ãåºãŸããã
ããã¯æéã§ãïŒ
real-world
ã®äŸã«åºã¥ããŠãUsagewithRouterãã¬ã·ããè¿œå ããŸãïŒclapïŒ
@gaearon _Usage with Router_ã®äŸãPRã«ããå Žåããã®åé¡ãåç §ã§ããŸããïŒ ç§ãç¥ã£ãŠããå€ãã®äººã ïŒç§èªèº«ãå«ãïŒã¯ãããã2ã€ãã©ã®ããã«ããŸãé£æºãããã«ã€ããŠã®èª¬æãæ¢ããŠããŸãã
ã¯ãã確ãã«ã ããã¯ãåé¡ã解決ããããšãã§ãã :-)
ãã¶ããredux-simple-routerãä»ããæ€èšããå¿ èŠããããŸããïŒ
redux-simple-router +1
ãŠãããŒãµã«ãªäŸ+ react-routerïŒ+ redux-simple-routerïŒãå€æããŸãã
https://github.com/eriknyk/redux-universal-app
ã¿ãªãããããã«ã¡ã¯ããã®è°è«ã®çµè«ã¯äœã§ããïŒ ç§ã¯ãreact-routerã§äœ¿çšããããã«ããã¥ã¡ã³ããæŽæ°ãããŠããªãããšã確èªããŸãã
cc @gaearon
@gaearonã¯ãreactã¢ããªã±ãŒã·ã§ã³ãreduxã«ãã€ã³ãããåŸãstateã䜿çšããŠã³ã³ããŒãã³ãã®è¡šç€º/é衚瀺ãå¶åŸ¡ããŸãã ãã®ãããRRã®ãããªå
ã®ãã«ãŒã¿ãŒãã®åœ¹å²ã¯çŸåšç§ã®ã¢ããªã±ãŒã·ã§ã³ã«é©åããŠããªããšæããŸãã
ãæ°ããã«ãŒã¿ãŒããè¡ãå¿
èŠããããšæãå¯äžã®ããšã¯ãURLãç¶æ
ã«ããããïŒã¢ã¯ã·ã§ã³ãä»ããŠïŒïŒãç¶æ
ãURLã«åãããããããšã§ãã
ã¢ããªã±ãŒã·ã§ã³ã³ã³ããŒãã³ãïŒãããããããã®äžéšïŒã®è¡šç€ºæ¹æ³ãurlã«æ±ºå®ããããšã2ã€ã®ç¶æ
ãœãŒã¹ããããŸãã1ã€ã¯urlã§ããã1ã€ã¯reduxã®ã¹ãã¢ã§ãããããã«ããç¶æ³ãé£ãããªããŸã...
ããã«ã€ããŠã©ãæããŸããïŒ ã¢ãã¬ã¹ããŒãã¢ããªã±ãŒã·ã§ã³ã®å¥ã®ã³ã³ããŒãã³ãã«ããå¿
èŠããããŸãã
ããããšã
https://github.com/rackt/react-router-redux/pull/259ãåºè·ããåŸããã®ããã¥ã¡ã³ããäœæããããšãæ£åŒã«çŽæããŸãã ããã¯ãReactRouterãšReduxããã€ã³ãããããã®ç¥çŠãããæ¹æ³ã«ãªããŸãã ããã¥ã¡ã³ãã§ã¯ãæåã«ãã®ããã±ãŒãžãªãã§ãããã䜿çšããæ¹æ³ã瀺ããããã±ãŒãžãæäŸãã2ã€ã®äŸ¿å©ããåŸã ã«çŽ¹ä»ããŸããããã«ãŠã§ã¢ãšä¿¡é Œã§ããå¯äžã®æ å ±æºã®ã¹ãã¢ãžã®ç§»åã§ãã ã©ã¡ãããªãã·ã§ã³ã§ãããããã©ã¡ãã®å Žåã«ãããã®äœ¿çšããªããã€ã³ããããããã³ããããããã©RRã«å¯ŸããŠäœãæäŸããããå¿ ã説æããŸãã
èæ ®ãã¹ãèãã¯æ¬¡ã®ãšããã§ããã«ãŒãã£ã³ã°ãšå±¥æŽã«é¢é£ããããã«ãŠã§ã¢ã«ã€ããŠèª¬æãããã®ããhttpïŒ//rackt.org/redux/docs/advanced/Middleware.htmlïŒ http://rackt.org/redux/docs/advanced/Middleware.html ïŒããšãã°ãæåŸã®äŸã§ã¯ïŒ
@gaearon React Routerã®ããã¥ã¡ã³ã/次ã®ã¹ãããã®é²æç¶æ³ã¯ïŒ ç§ã¯Reduxã®ããã¥ã¡ã³ããèªãã§ããŠããããæããŠããŸããããããã®åœã®ãªã³ã¯ã«æ©ãŸãããŠããŸã:(
ç§ã¯èªåã®å人ãªããžããªã§reactã«ãŒã¿ãŒã®ããã¥ã¡ã³ããæžãçŽãå§ããã°ããã§ãããã«ãreduxã»ã¯ã·ã§ã³ãèšããäºå®ã§ãã ç§ã¯ããã«äœãããããããããŸãããç§ã®èªç±ãªæéã«äŸåããŸãã ç§ã¯ããªããææ°ã®ç¶æ ã«ä¿ã¡ãŸãã https://github.com/knowbody/react-router-docs
å ¬å¹³ãæãããã«ãreactã«ãŒã¿ãŒãæ©èœãããããã«ReduxåŽã«ã¯äœãå¿ èŠãããŸããã ããããããããããè¡ãå¿ èŠããããŸãã
泚æïŒReact Router 3.0ã¯ãReact Redux connect()
ã®æé©åã§ããé©åã«æ©èœããæ°ããwithRouter()
HOCã¯ãã³ã³ããã¹ããçŽæ¥äœ¿çšããå¿
èŠããªãããšãæå³ããŸãã
@ gaearon ã @ timdorrã¯ãã«ãŒã¿ãŒã€ã³ã¹ã¿ã³ã¹ãåŒæ°ãšããŠã¢ã¯ã·ã§ã³äœæè ã«æž¡ãããšãšãbrowserHistoryãã¢ã¯ã·ã§ã³äœæè ã«çŽæ¥ã€ã³ããŒãããããšã®éã®ãã¬ãŒããªããæ確ã«ã§ããŸãïŒããã§ææ¡ãããŠããããã«https://github.com/reactjs/react-router/blob /master/docs/guides/NavigatingOutsideOfComponents.mdïŒ
router
ãå±¥æŽã€ã³ã¹ã¿ã³ã¹ãããã€ãã®è¿œå ã®æ©èœã§ã©ããããã ãã§ããã2ã€ã®ã€ã³ã¹ã¿ã³ã¹éã§åãpush
ïŒ$ã¡ãœãããšreplace
ã¡ãœããã§ãã
ããããšãã@ timdorrã
router
ãåºæ¬çã«å±¥æŽã·ã³ã°ã«ãã³ïŒã·ã³ã°ã«ãã³ã§ãïŒãã©ããããã®ã«ããªãwithRouter()
æ§æãå¿
èŠãªã®ããšãã質åã«ãªããšæããŸãã
ã³ã³ããŒãã³ããšå±¥æŽã€ã³ã¹ã¿ã³ã¹ã®éã®ããç·©ãçµåãå¯èœã«ããããã§ããïŒã€ãŸããã³ã³ããŒãã³ããã·ã³ã°ã«ãã³ãªããžã§ã¯ãã«çŽæ¥ã¢ã¯ã»ã¹ããã®ãé²ãããïŒïŒ ãããããªããã¢ã¯ã·ã§ã³ã¯ãªãšãŒã¿ãŒããå±¥æŽã€ã³ã¹ã¿ã³ã¹ã«ã¢ã¯ã»ã¹ãããšãã«åãããžãã¯ãé©çšãããŸãããïŒ
ã¯ããç¬èªã®å±¥æŽã€ã³ã¹ã¿ã³ã¹ãæäŸããç¬èªã®ã·ã³ã°ã«ãã³ã¢ãžã¥ãŒã«ãäœæããããªãïŒãŸãã¯äœæã§ããªãïŒå ŽåïŒJSã¢ãžã¥ãŒã«ã·ã¹ãã ã«ç²ŸéããŠããªãå Žåã¯æ··ä¹±ããå¯èœæ§ããããŸãïŒã ããªãããããèªåã§ããããã®ãªããããªãã¯ç§ãã¡ã®ãã¿ãŒã³ã«åŸãããšãæè¿ããŸãã
è€æ°ã®é«æ¬¡ã³ã³ããŒãã³ãã«ã©ã®ããã«äœ¿çšã§ãããã«ã€ããŠwithRouter
ãææžåãã䟡å€ããããã©ããã¯ããããŸããã ç§ã¯ãŸã ãããåé¿ããããã®æè¯ã®æ¹æ³ãèŠã€ããããšããŠããŸãïŒ
connect(mapStateToProps, mapDispatchToProps)(withRouter(withAnalytics(withLanguage(TestForm))));
ã
compose
ã®ãããªãã®ã䜿çšããããšãã§ããŸããïŒ
const enhance = compose(
connect(mapStateToProps, mapDispatchToProps),
withRouter,
withAnalytics,
withLanguage
);
export default enhance(TestForm);
ãã ããç§ã®ãŠãŒã¹ã±ãŒã¹ã§ã¯ãã³ã³ããã¹ãã«ãã°ã€ã³ãããŠãŒã¶ãŒãçŸåšã®èšèªãããŒãæ å ±ãããã³åæãå«ãŸãããããå€ãã®ã³ã³ããã¹ããšå€ãã®æ¥ç¶ãããã³ã³ããŒãã³ãã§ãããå°é£ã«ãªããŸãã
ãã1ã€ã®ã¢ã€ãã¢ã¯ã1ã€ã®ã³ã³ããã¹ãåå空éã®äžã§withRouter
ãšconnect
ããžãã¯ãè€è£œããããšã§ãã withAppContext() => props.app = { user, lang, theme, analytics, router, connect? }
ïŒ
ããã¯ãããã¥ã¡ã³ããŸãã¯connect
ã§ã®withRouter
ã®äœ¿çšäŸã«åœ¹ç«ã¡ãŸããïŒ
@gaearon React Router 3.0.0ãšæ°ããEggheadãããªããã°ããå ¬éãããŠããããã®ã¹ã¬ããã1幎ééãããŠããã®ã§ãããã«é¢ããæŽæ°ã¯ãããŸããïŒ
ïŒ1929ã§å®äº
æãåèã«ãªãã³ã¡ã³ã
ãŸããreactã«ãŒã¿ãŒãåºã䜿ãããŠããããšã瀺ãäŸãè¿œå ããããšã«ã€ããŠã©ãæããŸããïŒ