μ¬λλ€μ μ°λ¦¬κ° React Routerλ₯Ό μ§μνμ§ μκ±°λ μλνλ €λ©΄ redux-react-router μ κ°μ νΉλ³ν κ²μ΄ νμνκ±°λ μ¬μ§μ΄ React 0.14κΉμ§ μλνμ§ μλλ€λ μΈμμ λ°μ΅λλ€.
νμ¬μ ββκ°μ΄ Reduxλ₯Ό React Router 0.13 λλ 1.0κ³Ό ν¨κ» μ¬μ©ν μ μμ΅λλ€.
(κ·Έλ°λ° Reduxμ μ΄κΈ° λ¦΄λ¦¬μ€ μ΄νμλ μ¬μ€μ΄μμ΅λλ€.)
μκ° μ¬νκ³Ό κ°μ μΌλΆ κΈ°λ₯μ RR μΈ‘μμ μΌλΆ μ§μμ κΈ°λ€λ €μΌ νμ§λ§ μ΄λ μ£Όμ λ¬Έμ μ κ΄λ ¨μ΄ μμ΅λλ€. μ¬λλ€μ μ€λλ λΌμ°ν μ μ¬μ©ν μ μλ€κ³ μκ°νμ¬ νΌλμ€λ¬μν©λλ€. μ΄λ μλͺ»λ κ²μ λλ€.
μ΄ λ¦¬ν¬μ§ν 리μ ν¬ν¨λ μ€μ μμ λ React Routerλ₯Ό μ¬μ©ν©λλ€. λΌμ°ν°κ° μλ μ±μμ μ΅μμ κ΅¬μ± μμλ₯Ό λννλ κ²μ²λΌ <Router>
λ₯Ό <Provider>
λ‘ λννκΈ°λ§ νλ©΄ λ©λλ€.
μ‘μ
μμ±μμμ μ ννλ €λ©΄ router
μΈμ€ν΄μ€λ₯Ό μ‘μ
μμ±μμκ² λ§€κ°λ³μλ‘ μ λ¬νκ³ μνλ κ²½μ° ν΄λΉ λ©μλλ₯Ό νΈμΆν©λλ€. Redux μ μ₯μμμ λΌμ°ν° μνλ₯Ό μ½μΌλ €λ©΄ κ²½λ‘ λ³κ²½μ λν μμ
μ μ€ννκ³ μ΄λ₯Ό μ²λ¦¬ν 리λμλ₯Ό μμ±νμμμ€. κ·Έκ² λ€μΌ!
react-redux-router λ λΌμ°ν° μΈμ€ν΄μ€μ μλμΌλ‘ μ°κ²°λ μ μ₯μμμ μμ μ μ λ¬νκ³ μνλ₯Ό μ½μ μ μμ§λ§ μ¬μ©ν νμκ° μλ λ³΄λ€ μμ°μ€λ¬μ΄ APIλ₯Ό λ§λ€λ €λ μ€νμ λλ€. λλ μμ ν λ λκΉμ§ κΈ°λ€λ¦¬μμμ€! μ€νμΌ λΏμ λλ€.
μ°λ¦¬λ λ¬Έμμμ μ΄κ²μ΄ νμν©λλ€..
λλ μλ λ²μ© 컨ν μ€νΈμμ λ°μ λΌμ°ν°λ₯Ό μ¬μ©νκΈ° μν΄ μλ² μΈ‘ λ λλ§ μμ λ₯Ό μμ±νμ΅λλ€. λ°μ λΌμ°ν°μ ν¨κ» μ¬μ©νλ©΄ μ체 λ¬Έμκ° λ μ μλ€κ³ μ μλμμ΅λλ€. λ¬Έμμ μΉμ μ μΆκ°ν μ μμκΉμ?
λν, 리μ‘νΈ λΌμ°ν°κ° 보νΈμ μΌλ‘ μ¬μ©λλ μλ₯Ό μΆκ°νλ κ²μ λν΄ μ΄λ»κ² μκ°νμλκΉ?
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`.
무μμ΄ μλͺ»λμμ μ μμ΅λκΉ?
μΆμ : RR 1.0.0-λ² ν3
@gyzerok real-world
μμ κ° νλ κ²μ²λΌ μ 체 () => <Router>stuff</Router>
λ₯Ό <Provider>
$ λ‘ κ°μΈμΌ ν©λλ€.
@gaearon λ€, ofc. λλ κ·Έκ²μ 곡κΈμκ° μλλΌ λλΆλΆ λΉμ μ 곡κΈμμ 볡μ¬-λΆμ¬λ£κΈ°μΈ λ΄ μμ μ ꡬμ±μμμ ν¬μ₯ν©λλ€. μ°¨μ΄μ μ μ€ν μ΄λ₯Ό μ λ¬νμ§ μκ³ κ·Έ μμ μ€ν μ΄λ₯Ό μμ±νλ€λ κ²μ λλ€.
@gyzerok μ½λλ₯Ό λ³΄μ§ μκ³ λ 무μμ΄ μλͺ»λμλμ§ λ§νκΈ° μ΄λ ΅μ΅λλ€. (κ·Έλ¦¬κ³ λ³λμ νΈλ₯Ό μ μΆν΄ μ£ΌμΈμ. react-redux
repoκ° ββμ’μ κ³³μ
λλ€.)
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
κ²°κ³Όλ₯Ό νμ₯νλ €κ³ μλνμ§λ§ 컨ν
μ€νΈμ μ€μ λ¬Έμ κ° μμ΅λλ€. μκ°μ μ£ΌμΈμ. μ 체 μμ λ₯Ό λ³λμ μ μ₯μλ‘ νΈμνκ² μ΅λλ€.
λ΄κ° νμ¬ μ‘°μ¬νκ³ μλ λ λ€λ₯Έ κ²μ λͺ ννκ³ λμ κ±°μ¬λ¦¬μ§ μλ λ°©μμΌλ‘ redux μ μ₯μμ paramsλ₯Ό μ μ₯νλ κ²μ λλ€. λͺ κ°μ§ μ κ·Ό λ°©μμ μλν ν λ€μκ³Ό κ°μ΄ μμ±νμ΅λλ€.
<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 Routerμ Redux Routerκ° λͺ¨λ 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)μκ² μ리λ λ λ²μ§Έ μ¬μ©μ μ§μ κΈ°λ‘ κ΅¬νμΌλ‘ μμ±λ©λλ€. λν 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 λλ κ·Έκ²μ μ’μνμ§λ§ ν κ°μ§ μμ κ²μ΄ μμ΅λλ€. κ·νμ ꡬνμμ κ²½λ‘ λ³κ²½μ μμ
μ
λλ€. μ΄κ²μ "μμ
μ λͺ
λ Ήμ΄ μλ μ΄λ²€νΈ" μ κ·Ό λ°©μμ κΉ¨κ³ κ²°κ΅ μΌλΆ λΆμΎν κ΄νμΌλ‘ μ΄μ΄μ§ μ μμ΅λλ€. μκ°μ λ°κΏλ³΄μ. μ μ¬μ μΌλ‘ λͺ¨λ μμ
μ μ£Όμ νμμ€(κ΅¬μ± μμ λλ μ€μ λΈλΌμ°μ μ μ£Όμ νμμ€....)μ λ³κ²½νλ λΆμμ©μ μ΄λν μ μκ³ λΆμμ©μΌλ‘ μΈν΄ μ μμ
( ROUTE_CHANGED
)μ΄ λ°μ‘λ μ μμ΅λλ€. API νΈμΆμ νΈλ¦¬κ±°νλ κ²κ³Ό κΈ°λ³Έμ μΌλ‘ λμΌν ν¨ν΄μ
λλ€.
@tomkis1 νΌλλ°± μ£Όμ
μ κ°μ¬ν©λλ€. λ΄κ° λΉμ μ μ¬λ°λ₯΄κ² μ΄ν΄νλ€λ©΄ μ΄κ²μ μ€μ λ‘ μ΄λ―Έ κ·Έλ κ² μλν©λλ€. ROUTE
μ‘μ
μ URL λ³κ²½μ λΆμμ©μΌλ‘ μ λ¬λ©λλ€. ROUTE_CHANGED
κ° λ λμ μ΄λ¦μ΄ λ κΉμ?
μ€! λ°©κΈ λ λ² νμΈνκ³ λΉμ μ΄ μ³μμ΅λλ€. μ ROUTE_CHANGED
κ° λ μ’μ κ²μ
λλ€.
λλ κ·Έλ κ² μκ°ν΄. λ€μ λμκ°μ λ³κ²½νκ² μ§λ§ μ΄ λκΈμ μ λ§ νΌλμ€λ¬μΈ κ²μ λλ€. :)
νλ¦μ λ€μκ³Ό κ°μ΅λλ€.
URL λ³κ²½ -> ROUTE
(λλ ROUTE_CHANGED
) μμ
-> 리λμ μ
λ°μ΄νΈ μ μ₯μ -> μ μ₯μ κΈ°λ‘(μ΄μ μ μ μ₯μμ κ°μ
λ¨) 리μ€λμ μλ¦Ό -> λ°μ λΌμ°ν° μ
λ°μ΄νΈ
λλ UIμ μ¬μ©μ κ΄μ°° μνλ₯Ό ꡬλνλ μμ μΈμλ μ무κ²λ μνμ§ μκΈ° λλ¬Έμ μ΄κ²μ μ νΈν©λλ€. ν μ€νΈμ©μΌλ‘λ μ’μ κ² κ°μ΅λλ€.
μ΄ μ κ·Ό λ°©μμ λ¨μ μ URLμ΄ ROUTE_CHANGED
μμ
μ λν μλ΅μΌλ‘ μ
λ°μ΄νΈλμ§ μλλ€λ κ²μ
λλ€. μ‘μ
μ΄ λͺ
λ ΉμΌλ‘ μ²λ¦¬λλ κ²μ μνμ§ μλλ€λ©΄ μ΄κ²μ΄ λ°λμ§νμ§ νμ€νμ§ μμ§λ§ ROUTE_CHANGED
μ‘μ
μμ±μμ λΆμμ©μΌλ‘ λλ λ³λμ μμ κ°μ
μ.
BTW, μ΄ λ Όμκ° μ΄ λ¬Έμ μ λ²μλ₯Ό λ²μ΄λλ κ²½μ° μλ €μ£Όμλ©΄ μ΄λνκ² μ΅λλ€.
@cappslock λ무 μ’μμ! ROUTE_CHANGED
λ₯Ό λ°μ‘νλ€κ³ ν΄μ κ²½λ‘κ° λ°λμ§ μλ κ²μ νμ€ν λ¬Έμ κ° μλλΌκ³ μκ°ν©λλ€. μ‘μ
μ νΈλ¦¬κ±°κ° μλ μ΄λ²€νΈλ‘ μ²λ¦¬νλ κ²μ΄ λ λͺ
ννκ³ μ΄ν΄νκΈ° μ¬μ΄ κ² κ°μ΅λλ€(μ¬μ©μ μνΈ μμ©μ μλ΅νκΈ° λλ¬Έμ BUTTON_CLICKED
μ‘μ
μ΄ μ€μ λ‘ λ²νΌ ν΄λ¦μ νΈλ¦¬κ±°ν κ²μΌλ‘ κΈ°λνμ§ μμ κ²μ
λλ€). λ΄κ° μ΄ν΄νμ§ λͺ»νλ μ½λμ ν λΆλΆμ΄ μμ΅λλ€. μ΄ λΆλΆμ λν΄ μμΈν μ€λͺ
ν΄ μ£Όμκ² μ΅λκΉ?
μ΄κ²μ 첫 λ²μ§Έ κ²½λ‘κ° μ΄κΈ° λ λλ§μ νΈλ¦¬κ±°νλλ‘ λ§¨ μλμ λ°°μΉλ©λλ€.
@elliotdickison κ°μ¬ν©λλ€! λΆλͺ ν λ§μλλ¦¬κ² μ§λ§ κΉμ΄ μλ λΆμμ΄ μλ μνμ°©μ€μ κ°μ μ λ°νμΌλ‘ νλ λ§μμ΄λ λμ νκ² λ°μλ€μ΄μκΈ° λ°λλλ€. μ΄κ²μ μ΄ μμ μμ κ°λ /μ€μΌμΉμ μ¦λͺ μ κ°κΉμ΅λλ€.
ReactRouter
μ μΈμ€ν΄μ€ν μμ ν΄λΉ μ½λλ₯Ό λ°°μΉνμ λ /
κ²½λ‘μ ν΄λΉνλ κ΅¬μ± μμλ λ λλ§λμ§ μμμ΅λλ€. μμ
μ΄ μλμΌλ‘ λμ€ν¨μΉλκ±°λ μνκ° μλμΌλ‘ νΈμλ κ²½μ° λΌμ°ν°κ° κ³μ μλνλ―λ‘ νμ€ν 리μ μλͺ
μ£ΌκΈ° λ¬Έμ λΌκ³ μκ°νμ΅λλ€. ReactRouter
μ μΈμ€ν΄μ€ν μλλ‘ μ΄λνλ©΄ μ΄ λ¬Έμ κ° ν΄κ²°λμμ΅λλ€. λλ νμ€ν 리 λΌμ΄λΈλ¬λ¦¬κ° μ μ΄λ ν λͺ
μ ꡬλ
μκ° μμ λκΉμ§ μ΄κΈ° κ²½λ‘μ μλ¦Όμ μ°κΈ°νλ€κ³ μκ°ν©λλ€. ν΄λΉ ꡬλ
μκ° ReactRouterλ³΄λ€ λ¨Όμ μ€μ λλ©΄ μλ¦Όμ΄ λλ¬νμ§ μμ΅λλ€.
μ΄κ²μ μ€λͺ νλ €κ³ νλ©΄ λ΄ μ΄ν΄κ° μ½κ° λΆμ‘±νλ€λ κ²μ κΉ¨λ¬μμ΅λλ€. μ΄μ λν΄ λ μμλ³΄κ³ λ λμ λ΅λ³μ λ릴 μ μλλ‘ λ Έλ ₯νκ² μ΅λλ€.
μ΄ μ κ·Ό λ°©μμ λ¨μ μ ROUTE_CHANGED μμ μ λν μλ΅μΌλ‘ URLμ΄ μ λ°μ΄νΈλμ§ μλλ€λ κ²μ λλ€. μμ μ λͺ λ ΉμΌλ‘ μ²λ¦¬νμ§ μμΌλ €λ κ²½μ° μ΄κ²μ΄ λ°λμ§νμ§ νμ€νμ§ μμ§λ§ ROUTE_CHANGED μμ μμ±μμ λΆμμ©μΌλ‘ λλ λ³λμ μ€ν μ΄ κ΅¬λ μκ° μλ£ν μ μλ€κ³ μκ°ν©λλ€.
λλ μ΄κ²μ΄ λ°λμ§νλ€κ³ λ§νκ³ μΆμ΅λλ€. ROUTE_CHANGED
λ νμ€ν μΈλΆ μμ€(μ: onhashchange...)μ μν΄ μ€νλμ΄μΌ ν©λλ€. IMO URL λ³κ²½μ κ·Έ λ°λκ° μλλΌ ROUTE_CHANGED
μ΄ λμ΄μΌ ν©λλ€.
λμν©λλ€. λμ€ν¨μΉλ ROUTE_CHANGED
μ‘μ
μ΄ μ€μ νμ€ν 리 μ΄λ²€νΈκ° μλ μ½λμμ μμλ κ²½μ°λ₯Ό λλΉνμ¬ μ€ν μ΄λ₯Ό ꡬλ
νκ³ URLμ λκΈ°νλ μνλ‘ μ μ§νλ κ²μ΄ μ’μ κ²μ΄λΌκ³ μκ°νμ§λ§ κ·Έ κ²½μ°κ° λ€μμ λνλΈλ€κ³ μ£Όμ₯ν μ μμ΅λλ€. νλ‘κ·Έλλ° μ€λ₯.
@cappslock λΉμ μ μ κ·Ό λ°©μμ μ λ§ μ λ§ μ’μ΅λλ€. κ·Έκ²μ λν΄ λΈλ‘κ·Έ ν¬μ€νΈλ₯Ό λ§λ€ μ μμ΅λκΉ?
@vojtatranta https://github.com/rackt/redux/issues/805 λ₯Ό νμΈνμμμ€. ꡬνμ μκ°μ μ€ κ² κ°μ΅λλ€.
@vojtatranta κ°μ¬ν©λλ€! λλ λΈλ‘κ·Έκ° μκΈ° λλ¬Έμ κ±°μ λͺ¨λ μ λ³΄κ° μ΄ μ€λ λμ #805μ μμ΅λλ€. νΉν λ λ§μ μ 보λ₯Ό μνμ ¨λμ?
1.0μ΄ λμμ΅λλ€.
λ€μμ μνν μκ°μ λλ€.
real-world
μμ λ₯Ό κΈ°λ°μΌλ‘ "λΌμ°ν° μ¬μ©" λ μνΌ μΆκ°:λ°μ:
@gaearon _Usage with Router_ μμ κ° PRμ μμ λ μ΄ λ¬Έμ λ₯Ό μ°Έμ‘°ν μ μμ΅λκΉ? λ΄κ° μλ λ§μ μ¬λλ€(μ λ₯Ό ν¬ν¨νμ¬)μ μ΄ λ κ°μ§κ° μ΄λ»κ² ν¨κ» μ μλνλμ§μ λν μ€λͺ μ μ°Ύκ³ μμ΅λλ€.
λ¬Όλ‘ μ΄μ§. λ¬Έμ κ° μ’ λ£λλ μμ μ λλ€. :-)
μ΄μ redux-simple-router λ₯Ό κ³ λ €ν΄μΌ ν κΉμ?
redux-simple-router +1
λ°©κΈ λ²μ© μμ + react-router(+redux-simple-router)λ₯Ό λ³ννμ΅λλ€.
https://github.com/eriknyk/redux-universal-app
μλ
μ¬λ¬λΆ, μ΄ ν λ‘ μ κ²°λ‘ μ 무μμ
λκΉ? λλ λ¬Έμκ° react-routerμ ν¨κ» μ¬μ©νλλ‘ μ
λ°μ΄νΈλμ§ μμ κ²μ λ΄
λλ€.
cc @gaearon
@gaearon λ΄ λ°μ μμ© νλ‘κ·Έλ¨μ reduxμ λ°μΈλ©ν ν μνλ₯Ό μ¬μ©νμ¬ κ΅¬μ± μμμ νμ/μ¨κΉμ μ μ΄ν©λλ€. κ·Έλμ μ λ RRκ³Ό κ°μ μλμ "λΌμ°ν°" μν μ΄ μ§κΈ μ μ ν리μΌμ΄μ
μ μ ν©νμ§ μλ€κ³ μκ°ν©λλ€.
"μ λΌμ°ν°"κ° ν΄μΌ ν μΌμ URLμ μνμ 맀ννκ³ (λμμ ν΅ν΄?) μνλ₯Ό λ€μ urlμ λ€μ 맀ννλ κ²λΏμ΄λΌκ³ μκ°ν©λλ€.
urlμ΄ μμ© νλ‘κ·Έλ¨ κ΅¬μ± μμ(κ·Έ μ€ μΌλΆ)κ° νμλλ λ°©λ²μ κ²°μ νκ² νλ©΄ μν μμ€κ° λ κ° μμ΅λλ€. νλλ urlμ΄κ³ λ€λ₯Έ νλλ reduxμ μ μ₯μμ΄λ―λ‘ μν©μ΄ λ μ΄λ €μμ§λλ€...
μ΄μ λν΄ λλΌκ³ ν©λκΉ? μ£Όμ νμμ€μ μμ© νλ‘κ·Έλ¨ κ΅¬μ± μμμ λ λ€λ₯Έ κ΅¬μ± μμλ‘ λμ΄μΌ ν©λλ€.
κ°μ¬ ν΄μ
https://github.com/rackt/react-router-redux/pull/259λ₯Ό μΆμν ν 곡μμ μΌλ‘ μ΄ λ¬Έμλ₯Ό μμ±ν κ²μ μ½μν©λλ€. μ΄κ²μ React Routerμ Reduxλ₯Ό λ°μΈλ©νλ μΆλ³΅λ λ°©λ²μ΄ λ κ²μ λλ€. λ¬Έμμμ λ¨Όμ ν΄λΉ ν¨ν€μ§ μμ΄ μ¬μ©νλ λ°©λ²μ 보μ¬μ£Όκ³ ν¨ν€μ§κ° μ 곡νλ λ κ°μ§ νΈλ¦¬ν¨μ μ μ§μ μΌλ‘ μκ°ν©λλ€. λ―Έλ€μ¨μ΄μ λΌμ°ν μμ€λ₯Ό μ μ₯μλ‘ μ΄λνλ κ²μ λλ€. λ λ€ μ ν μ¬νμ΄λ―λ‘ μ¬μ©νκΈ°λ‘ μ ννλ κ²½μ°μ κΈ°λ³Έ RRμ λν΄ μ 곡νλ μ¬νμ νμ€ν μ€λͺ νκ² μ΅λλ€.
μ¬κΈ°μ κ³ λ €ν΄μΌ ν μκ°μ΄ μμ΅λλ€. λΌμ°ν λ° κΈ°λ‘κ³Ό κ΄λ ¨λ λ―Έλ€μ¨μ΄μ λν΄ μ€λͺ νλ κ²μ΄ http://rackt.org/redux/docs/advanced/Middleware.html μ μΌλ°μ μΈ μ€λͺ λ΄μμ μ€μ μμ© νλ‘κ·Έλ¨μ νΉμ λΆλΆμ΄ λ μ μλ κ²½μ°( μλ₯Ό λ€μ΄ λμ μλ μμ μμ)
@gaearon React Router λ¬Έμ/λ€μ λ¨κ³μ λν μ§ν μν©μ΄ μμ΅λκΉ? λλ Redux λ¬Έμλ₯Ό μ½κ³ κ·Έκ²μ μ¬λνμ§λ§ κ·Έ κ°μ§ λ§ν¬μ μν΄ λΆλλ¬μν©λλ€ :(
λλ λ¨μ§ λ΄ κ°μΈ repoμμ react λΌμ°ν° λ¬Έμλ₯Ό λ€μ μμ±νκΈ° μμνκ³ κ±°κΈ°μλ redux μΉμ μ κ°μ§ κ³νμ λλ€. λ΄ μμ μκ°μ λ°λΌ 곧 ν μΌμ΄ μμ μ μμ΅λλ€. κ³μ μ λ°μ΄νΈνκ² μ΅λλ€. https://github.com/knowbody/react-router-docs
곡ννκ² λ°μ λΌμ°ν°κ° μλνλλ‘ νκΈ° μν΄ 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
λ κΈ°λ‘ μΈμ€ν΄μ€λ₯Ό λͺ κ°μ§ μΆκ° νλͺ©μΌλ‘ λννμ§λ§ λ μΈμ€ν΄μ€ κ°μ λμΌν 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);
κ·Έλ¬λ λ΄ μ¬μ© μ¬λ‘ 컨ν μ€νΈμλ λ‘κ·ΈμΈν μ¬μ©μ, νμ¬ μΈμ΄, ν λ§ μ 보 λ° λΆμμ΄ ν¬ν¨λμ΄ μμ΄ λ§μ 컨ν μ€νΈμ μ°κ²°λ κ΅¬μ± μμκ° λ§μ μ΄λ₯Ό μ΄λ ΅κ² λ§λλλ€.
λ€λ₯Έ μμ΄λμ΄λ withRouter
λ° connect
λ
Όλ¦¬λ₯Ό νλμ 컨ν
μ€νΈ λ€μμ€νμ΄μ€ μλμ 볡μ νλ κ²μ
λλ€. withAppContext() => props.app = { user, lang, theme, analytics, router, connect? }
?
μ΄κ²μ λ¬Έμλ connect
withRouter
μ¬μ©μ μμ λμμ΄ λ κΉμ?
@gaearon React Router 3.0.0κ³Ό μλ‘μ΄ Egghead λμμμ΄ λμ¨ μ§ μΌλ§ λμ§ μμκ³ μ΄ μ€λ λκ° μ΄λ¦° μ§ 1λ μ΄ λ μ§κΈ μ΄μ λν μ λ°μ΄νΈκ° μμ΅λκΉ?
#1929μμ μλ£
κ°μ₯ μ μ©ν λκΈ
λν, 리μ‘νΈ λΌμ°ν°κ° 보νΈμ μΌλ‘ μ¬μ©λλ μλ₯Ό μΆκ°νλ κ²μ λν΄ μ΄λ»κ² μκ°νμλκΉ?