Redux: react-router의 경둜 μ „ν™˜μ— λŒ€ν•œ μ‘λ‹΅μœΌλ‘œ μž‘μ—… μ‹€ν–‰

에 λ§Œλ“  2015λ…„ 07μ›” 07일  Β·  26μ½”λ©˜νŠΈ  Β·  좜처: reduxjs/redux

μ•ˆλ…•ν•˜μ„Έμš” μ—¬λŸ¬λΆ„,

μ΅œμ‹  μ•±μ—μ„œ react-router 및 reduxλ₯Ό μ‚¬μš©ν•˜κ³  있으며 ν˜„μž¬ URL 맀개 λ³€μˆ˜ 및 쿼리에 따라 ν•„μš”ν•œ μƒνƒœ λ³€κ²½κ³Ό κ΄€λ ¨λœ λͺ‡ 가지 λ¬Έμ œμ— μ§λ©΄ν•˜κ³  μžˆμŠ΅λ‹ˆλ‹€.

기본적으둜 URL이 λ³€κ²½ 될 λ•Œλ§ˆλ‹€ μƒνƒœλ₯Ό μ—…λ°μ΄νŠΈν•΄μ•Όν•˜λŠ” ꡬ성 μš”μ†Œκ°€ μžˆμŠ΅λ‹ˆλ‹€. μƒνƒœλŠ” μ΄λ ‡κ²Œ λ°μ½”λ ˆμ΄ν„°λ₯Ό μ‚¬μš©ν•˜μ—¬ redux에 μ˜ν•΄ propsλ₯Ό 톡해 μ „λ‹¬λ©λ‹ˆλ‹€.

 @connect(state => ({
   campaigngroups: state.jobresults.campaigngroups,
   error: state.jobresults.error,
   loading: state.jobresults.loading
 }))

URL이 this.props.params 및 this.props.query μ—μ„œ λ³€κ²½ 될 λ•Œ react-routerκ°€ ν•Έλ“€λŸ¬μ— μƒˆλ‘œμš΄ propsλ₯Ό μ „λ‹¬ν•˜κΈ° λ•Œλ¬Έμ— react-routerμ—μ„œ μ˜€λŠ” URL 변경에 μ‘λ‹΅ν•˜κΈ° μœ„ν•΄ componentWillReceiveProps lifecycle λ©”μ„œλ“œλ₯Ό μ‚¬μš©ν•˜κ³  μžˆμŠ΅λ‹ˆλ‹€. this.props.query -이 μ ‘κ·Ό λ°©μ‹μ˜ μ£Όμš” λ¬Έμ œλŠ” μƒνƒœλ₯Ό μ—…λ°μ΄νŠΈν•˜κΈ° μœ„ν•΄μ΄ λ©”μ„œλ“œμ—μ„œ μž‘μ—…μ„ μ‹€ν–‰ν•˜κ³  μžˆλ‹€λŠ” κ²ƒμž…λ‹ˆλ‹€. 그런 λ‹€μŒ λ™μΌν•œ 수λͺ…μ£ΌκΈ° λ©”μ„œλ“œλ₯Ό λ‹€μ‹œ νŠΈλ¦¬κ±°ν•˜λŠ” ꡬ성 μš”μ†Œμ— μƒˆ propsλ₯Ό μ „λ‹¬ν•©λ‹ˆλ‹€. λ”°λΌμ„œ 기본적으둜 λ¬΄ν•œ 생성 루프, ν˜„μž¬ λ‚˜λŠ” 이것을 막기 μœ„ν•΄ μƒνƒœ λ³€μˆ˜λ₯Ό μ„€μ •ν•˜κ³  μžˆμŠ΅λ‹ˆλ‹€.

  componentWillReceiveProps(nextProps) {
    if (this.state.shouldupdate) {
      let { slug } = nextProps.params;
      let { citizenships, discipline, workright, location } = nextProps.query;
      const params = { slug, discipline, workright, location };
      let filters = this._getFilters(params);
      // set the state accroding to the filters in the url
      this._setState(params);
      // trigger the action to refill the stores
      this.actions.loadCampaignGroups(filters);
    }
  }

경둜 μ „ν™˜μ„ 기반으둜 μž‘μ—…μ„ νŠΈλ¦¬κ±°ν•˜λŠ” ν‘œμ€€ μ ‘κ·Ό 방식이 μžˆμŠ΅λ‹ˆκΉŒ? μ•„λ‹ˆλ©΄ μ†Œν’ˆμ„ 톡해 μ „λ‹¬ν•˜λŠ” λŒ€μ‹  ꡬ성 μš”μ†Œμ˜ μƒνƒœμ— μƒμ μ˜ μƒνƒœλ₯Ό 직접 μ—°κ²°ν•  수 μžˆμŠ΅λ‹ˆκΉŒ? willTransitionTo 정적 λ©”μ„œλ“œλ₯Ό μ‚¬μš©ν•˜λ €κ³ ν–ˆμ§€λ§Œ this.props.dispatch에 μ•‘μ„ΈμŠ€ ν•  수 μ—†μŠ΅λ‹ˆλ‹€.

docs ecosystem question

κ°€μž₯ μœ μš©ν•œ λŒ“κΈ€

@deowk 이 λ¬Έμ œμ—λŠ” 두 뢀뢄이 μžˆμŠ΅λ‹ˆλ‹€. 첫 λ²ˆμ§ΈλŠ” componentWillReceiveProps() 은 μƒνƒœ 변경에 μ‘λ‹΅ν•˜λŠ” 데 이상적인 방법이 μ•„λ‹ˆλΌλŠ” κ²ƒμž…λ‹ˆλ‹€. λŒ€λΆ€λΆ„ Reduxμ—μ„œ ν•˜λŠ” κ²ƒμ²˜λŸΌ 적 으둜 생각 λͺ…λ Ή 적 으둜 μƒκ°ν•΄μ•Όν•˜κΈ° λ•Œλ¬Έμž…λ‹ˆλ‹€. 해결책은 ν˜„μž¬ λΌμš°ν„° 정보 (μœ„μΉ˜, 맀개 λ³€μˆ˜, 쿼리)λ₯Ό _inside_ μ €μž₯μ†Œμ— μ €μž₯ν•˜λŠ” κ²ƒμž…λ‹ˆλ‹€. 그러면 λͺ¨λ“  μƒνƒœκ°€ λ™μΌν•œ μœ„μΉ˜μ— 있고 λ‚˜λ¨Έμ§€ 데이터와 λ™μΌν•œ Redux APIλ₯Ό μ‚¬μš©ν•˜μ—¬ ꡬ독 ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

νŠΈλ¦­μ€ λΌμš°ν„° μœ„μΉ˜κ°€ λ³€κ²½ 될 λ•Œλ§ˆλ‹€ μ‹€ν–‰λ˜λŠ” μž‘μ—… μœ ν˜•μ„ λ§Œλ“œλŠ” κ²ƒμž…λ‹ˆλ‹€. 이것은 곧 μΆœμ‹œ 될 React Router 1.0 λ²„μ „μ—μ„œ μ‰½μŠ΅λ‹ˆλ‹€.

// routeLocationDidUpdate() is an action creator
// Only call it from here, nowhere else
BrowserHistory.listen(location => dispatch(routeLocationDidUpdate(location)));

이제 상점 μƒνƒœλŠ” 항상 λΌμš°ν„° μƒνƒœμ™€ λ™κΈ°ν™”λ©λ‹ˆλ‹€. 그러면 μœ„μ˜ ꡬ성 μš”μ†Œμ—μ„œ 쿼리 맀개 λ³€μˆ˜ λ³€κ²½ 및 setState() 에 μˆ˜λ™μœΌλ‘œ λ°˜μ‘ ν•  ν•„μš”κ°€ μ—†μŠ΅λ‹ˆλ‹€. Redux의 컀λ„₯ν„°λ₯Ό μ‚¬μš©ν•˜κΈ° λ§Œν•˜λ©΄λ©λ‹ˆλ‹€.

<Connector select={state => ({ filter: getFilters(store.router.params) })} />

문제의 두 번째 뢀뢄은 경둜 변경에 λŒ€ν•œ μ‘λ‹΅μœΌλ‘œ μž‘μ—…μ„ μ‹€ν–‰ν•˜λŠ” 것과 같이 λ·° λ ˆμ΄μ–΄ μ™ΈλΆ€μ˜ Redux μƒνƒœ 변경에 λŒ€μ‘ν•˜λŠ” 방법이 ν•„μš”ν•˜λ‹€λŠ” κ²ƒμž…λ‹ˆλ‹€. μ›ν•˜λŠ” 경우 μ„€λͺ…ν•˜λŠ” 것과 같은 κ°„λ‹¨ν•œ κ²½μš°μ— componentWillReceivePropsλ₯Ό 계속 μ‚¬μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

ν•˜μ§€λ§Œ 더 λ³΅μž‘ν•œ 경우라면 RxJSλ₯Ό μ‚¬μš©ν•˜λŠ” 것이 μ’‹μŠ΅λ‹ˆλ‹€. 이것이 λ°”λ‘œ μ˜΅μ €λ²„ 블이 μ„€κ³„λœ λ°˜μ‘ 데이터 νλ¦„μž…λ‹ˆλ‹€.

Reduxμ—μ„œμ΄λ₯Ό μˆ˜ν–‰ν•˜λ €λ©΄ λ¨Όμ € κ΄€μ°° κ°€λŠ₯ν•œ μŠ€ν† μ–΄ μƒνƒœ μ‹œν€€μŠ€λ₯Ό μƒμ„±ν•©λ‹ˆλ‹€. redux-rx의 observableFromStore() μ‚¬μš©ν•˜μ—¬μ΄λ₯Ό μˆ˜ν–‰ ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

import { observableFromStore } from 'redux-rx';
const state$ = observableFromStore(store);

그런 λ‹€μŒ νŠΉμ • μƒνƒœ 변경을 κ΅¬λ…ν•˜κΈ° μœ„ν•΄ κ΄€μ°° κ°€λŠ₯ν•œ μ—°μ‚°μžλ₯Ό μ‚¬μš©ν•˜λ©΄λ©λ‹ˆλ‹€. λ‹€μŒμ€ 성곡적인 둜그인 ν›„ 둜그인 νŽ˜μ΄μ§€μ—μ„œ λ¦¬λ””λ ‰μ…˜ν•˜λŠ” μ˜ˆμž…λ‹ˆλ‹€.

const didLogin$ = state$
  .distinctUntilChanged(state => !state.loggedIn && state.router.path === '/login')
  .filter(state => state.loggedIn && state.router.path === '/login');

didLogin$.subscribe({
   router.transitionTo('/success');
});

이 κ΅¬ν˜„μ€ componentDidReceiveProps() 와 같은 λͺ…λ Ήν˜• νŒ¨ν„΄μ„ μ‚¬μš©ν•˜λŠ” λ™μΌν•œ κΈ°λŠ₯보닀 훨씬 κ°„λ‹¨ν•©λ‹ˆλ‹€.

도움이 λ˜μ—ˆκΈ°λ₯Ό λ°”λžλ‹ˆλ‹€.

λͺ¨λ“  26 λŒ“κΈ€

@deowk this.props 와 nextProps λ₯Ό λΉ„κ΅ν•˜μ—¬ κ΄€λ ¨ 데이터가 λ³€κ²½λ˜μ—ˆλŠ”μ§€ 확인할 수 μžˆμŠ΅λ‹ˆλ‹€. λ³€κ²½λ˜μ§€ μ•Šμ€ 경우 μž‘μ—…μ„ λ‹€μ‹œ 트리거 ν•  ν•„μš”κ°€ μ—†μœΌλ©° λ¬΄ν•œ 루프λ₯Ό λ²—μ–΄λ‚  수 μžˆμŠ΅λ‹ˆλ‹€.

@johanneslumpe : 제 κ²½μš°μ—λŠ” 캠페인 그룹이 λ‹€μ†Œ 큰 개체 λͺ¨μŒμž…λ‹ˆλ‹€. 이런 μ‹μœΌλ‘œ κΉŠμ€ 개체 비ꡐλ₯Ό 쑰건으둜 μ‚¬μš©ν•˜λŠ” 것이 λΉ„νš¨μœ¨μ  인 것 κ°™μŠ΅λ‹ˆλ‹€.

@deowk λΆˆλ³€ 데이터λ₯Ό μ‚¬μš©ν•˜λ©΄ μ°Έμ‘°λ₯Ό 비ꡐ할 수 μžˆμŠ΅λ‹ˆλ‹€.

@deowk 이 λ¬Έμ œμ—λŠ” 두 뢀뢄이 μžˆμŠ΅λ‹ˆλ‹€. 첫 λ²ˆμ§ΈλŠ” componentWillReceiveProps() 은 μƒνƒœ 변경에 μ‘λ‹΅ν•˜λŠ” 데 이상적인 방법이 μ•„λ‹ˆλΌλŠ” κ²ƒμž…λ‹ˆλ‹€. λŒ€λΆ€λΆ„ Reduxμ—μ„œ ν•˜λŠ” κ²ƒμ²˜λŸΌ 적 으둜 생각 λͺ…λ Ή 적 으둜 μƒκ°ν•΄μ•Όν•˜κΈ° λ•Œλ¬Έμž…λ‹ˆλ‹€. 해결책은 ν˜„μž¬ λΌμš°ν„° 정보 (μœ„μΉ˜, 맀개 λ³€μˆ˜, 쿼리)λ₯Ό _inside_ μ €μž₯μ†Œμ— μ €μž₯ν•˜λŠ” κ²ƒμž…λ‹ˆλ‹€. 그러면 λͺ¨λ“  μƒνƒœκ°€ λ™μΌν•œ μœ„μΉ˜μ— 있고 λ‚˜λ¨Έμ§€ 데이터와 λ™μΌν•œ Redux APIλ₯Ό μ‚¬μš©ν•˜μ—¬ ꡬ독 ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

νŠΈλ¦­μ€ λΌμš°ν„° μœ„μΉ˜κ°€ λ³€κ²½ 될 λ•Œλ§ˆλ‹€ μ‹€ν–‰λ˜λŠ” μž‘μ—… μœ ν˜•μ„ λ§Œλ“œλŠ” κ²ƒμž…λ‹ˆλ‹€. 이것은 곧 μΆœμ‹œ 될 React Router 1.0 λ²„μ „μ—μ„œ μ‰½μŠ΅λ‹ˆλ‹€.

// routeLocationDidUpdate() is an action creator
// Only call it from here, nowhere else
BrowserHistory.listen(location => dispatch(routeLocationDidUpdate(location)));

이제 상점 μƒνƒœλŠ” 항상 λΌμš°ν„° μƒνƒœμ™€ λ™κΈ°ν™”λ©λ‹ˆλ‹€. 그러면 μœ„μ˜ ꡬ성 μš”μ†Œμ—μ„œ 쿼리 맀개 λ³€μˆ˜ λ³€κ²½ 및 setState() 에 μˆ˜λ™μœΌλ‘œ λ°˜μ‘ ν•  ν•„μš”κ°€ μ—†μŠ΅λ‹ˆλ‹€. Redux의 컀λ„₯ν„°λ₯Ό μ‚¬μš©ν•˜κΈ° λ§Œν•˜λ©΄λ©λ‹ˆλ‹€.

<Connector select={state => ({ filter: getFilters(store.router.params) })} />

문제의 두 번째 뢀뢄은 경둜 변경에 λŒ€ν•œ μ‘λ‹΅μœΌλ‘œ μž‘μ—…μ„ μ‹€ν–‰ν•˜λŠ” 것과 같이 λ·° λ ˆμ΄μ–΄ μ™ΈλΆ€μ˜ Redux μƒνƒœ 변경에 λŒ€μ‘ν•˜λŠ” 방법이 ν•„μš”ν•˜λ‹€λŠ” κ²ƒμž…λ‹ˆλ‹€. μ›ν•˜λŠ” 경우 μ„€λͺ…ν•˜λŠ” 것과 같은 κ°„λ‹¨ν•œ κ²½μš°μ— componentWillReceivePropsλ₯Ό 계속 μ‚¬μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

ν•˜μ§€λ§Œ 더 λ³΅μž‘ν•œ 경우라면 RxJSλ₯Ό μ‚¬μš©ν•˜λŠ” 것이 μ’‹μŠ΅λ‹ˆλ‹€. 이것이 λ°”λ‘œ μ˜΅μ €λ²„ 블이 μ„€κ³„λœ λ°˜μ‘ 데이터 νλ¦„μž…λ‹ˆλ‹€.

Reduxμ—μ„œμ΄λ₯Ό μˆ˜ν–‰ν•˜λ €λ©΄ λ¨Όμ € κ΄€μ°° κ°€λŠ₯ν•œ μŠ€ν† μ–΄ μƒνƒœ μ‹œν€€μŠ€λ₯Ό μƒμ„±ν•©λ‹ˆλ‹€. redux-rx의 observableFromStore() μ‚¬μš©ν•˜μ—¬μ΄λ₯Ό μˆ˜ν–‰ ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

import { observableFromStore } from 'redux-rx';
const state$ = observableFromStore(store);

그런 λ‹€μŒ νŠΉμ • μƒνƒœ 변경을 κ΅¬λ…ν•˜κΈ° μœ„ν•΄ κ΄€μ°° κ°€λŠ₯ν•œ μ—°μ‚°μžλ₯Ό μ‚¬μš©ν•˜λ©΄λ©λ‹ˆλ‹€. λ‹€μŒμ€ 성곡적인 둜그인 ν›„ 둜그인 νŽ˜μ΄μ§€μ—μ„œ λ¦¬λ””λ ‰μ…˜ν•˜λŠ” μ˜ˆμž…λ‹ˆλ‹€.

const didLogin$ = state$
  .distinctUntilChanged(state => !state.loggedIn && state.router.path === '/login')
  .filter(state => state.loggedIn && state.router.path === '/login');

didLogin$.subscribe({
   router.transitionTo('/success');
});

이 κ΅¬ν˜„μ€ componentDidReceiveProps() 와 같은 λͺ…λ Ήν˜• νŒ¨ν„΄μ„ μ‚¬μš©ν•˜λŠ” λ™μΌν•œ κΈ°λŠ₯보닀 훨씬 κ°„λ‹¨ν•©λ‹ˆλ‹€.

도움이 λ˜μ—ˆκΈ°λ₯Ό λ°”λžλ‹ˆλ‹€.

μƒˆ λ¬Έμ„œμ—μ„œ ν•„μš”ν•©λ‹ˆλ‹€. λ„ˆλ¬΄ 잘 μ“°μ—¬μ‘ŒμŠ΅λ‹ˆλ‹€.

@acdlite : λŒ€λ‹¨νžˆ κ°μ‚¬ν•©λ‹ˆλ‹€. κ·€ν•˜μ˜ 쑰언은 정말 μ €λ₯Ό 많이 λ„μ™”μŠ΅λ‹ˆλ‹€.ν•˜μ§€λ§Œ URL 변경에 λŒ€ν•œ μ‘λ‹΅μœΌλ‘œ μ•‘μ…˜ 크리에이터λ₯Ό νŠΈλ¦¬κ±°ν•˜μ—¬ μŠ€ν† μ–΄μ—μ„œ μƒνƒœλ₯Ό λ³€κ²½ν•˜λŠ” 데 어렀움을 κ²ͺκ³  μžˆμŠ΅λ‹ˆλ‹€.

이것은 react-router v0.13.3의 μœ μΌν•œ μ˜΅μ…˜μ²˜λŸΌ 보이기 λ•Œλ¬Έμ— willTransitionTo 정적 λ©”μ„œλ“œμ—μ„œ μ•‘μ…˜ μƒμ„±μžλ₯Ό νŠΈλ¦¬κ±°ν•˜κ³  μ‹ΆμŠ΅λ‹ˆλ‹€.

class Results extends Component  {
..........
}

Results.willTransitionTo = function (transition, params, query) {
 // how do I get a reference to dispatch here?
};

@deowk λ‚΄ 생각 μ—” redux μΈμŠ€ν„΄μŠ€μ—μ„œ 직접 dispatch ν˜ΈμΆœν•˜λŠ” κ²ƒμž…λ‹ˆλ‹€.

const redux = createRedux(stores);
BrowserHistory.listen(location => redux.dispatch(routeLocationDidUpdate(location)));

@deowk ν˜„μž¬ λ‹€μŒκ³Ό 같이 λ°˜μ‘ λΌμš°ν„° 0.13.3μ—μ„œ URL λ³€κ²½ 사항을 λ°œμ†‘ν•©λ‹ˆλ‹€.

Router.run(routes, Router.HistoryLocation, function(Handler, locationState) {
   dispatch(routeLocationDidUpdate(locationState))
   React.render(<Handler/>, appEl);
});

@acdlite 정말 잘 μ„€λͺ…ν–ˆμŠ΅λ‹ˆλ‹€! : +1 :
μƒˆ λ¬Έμ„œμ—λ„ μžˆμ–΄μ•Όν•œλ‹€λŠ” 데 λ™μ˜ν•©λ‹ˆλ‹€. :)

참고둜 BrowserHistory.history() 이 BrowserHistory.addChangeListener() λ³€κ²½λ˜μ—ˆμŠ΅λ‹ˆλ‹€.

https://github.com/rackt/react-router/blob/master/modules/BrowserHistory.js#L57

νŽΈμ§‘ν•˜λ‹€:

λ‹€μŒκ³Ό 같이 보일 수 μžˆμŠ΅λ‹ˆλ‹€.

history.addChangeListener(() => store.dispatch(routeLocationDidUpdate(location)));

그리고 감속기 @pburtchaell의 초기 μƒνƒœλŠ” μ–΄λ–»μŠ΅λ‹ˆκΉŒ?

λ‹€μŒ 섀정이 μžˆμŠ΅λ‹ˆλ‹€.

// client.js
class App extends Component {
  constructor(props) {
    super(props);
    this.history = new HashHistory();
  }

  render() {
    return (
      <Provider store={store}>
         {renderRoutes.bind(null, this.history)}
      </Provider>
    );
  }
}

// routes.js
export default function renderRoutes(history) {

  // When the route changes, dispatch that information to the store.
  history.addChangeListener(() => store.dispatch(routeLocationDidUpdate(location)));

  return (
    <Router history={history}>
      <Route component={myAppView}>
        <Route path="/" component={myHomeView}  />
      </Route>
    </Router>
  );
};

μ΄λ ‡κ²Œν•˜λ©΄ κ²½λ‘œκ°€ λ³€κ²½ 될 λ•Œμ™€ 앱이 μ²˜μŒλ‘œλ“œ 될 λ•Œλ§ˆλ‹€ routeLocationDidUpdate() μž‘μ—… 생성기가 μ‹€ν–‰λ©λ‹ˆλ‹€.

@pburtchaell 당신은 λ‹Ήμ‹ μ˜ routeLocationDidUpdate λ₯Ό 곡유 ν•  수 μžˆμŠ΅λ‹ˆκΉŒ?

@gyzerok λ¬Όλ‘ μž…λ‹ˆλ‹€. μ•‘μ…˜ ν¬λ¦¬μ—μ΄ν„°μž…λ‹ˆλ‹€.

// actions/location.js
export function routeLocationDidUpdate(location) {
  return {
    type: 'LOCATION_UPDATE',
    payload: {
      ...location,
    },
  };
}

@pburtchaell κ·Έλž˜μ„œ κ·€ν•˜μ˜ μ˜ˆμ—μ„œλŠ” νŠΉμ • κ²½λ‘œμ— ν•„μš”ν•œ 데이터λ₯Ό μ–΄λ””μ—μ„œ κ°€μ Έ μ˜€λŠ”μ§€ 쑰용히 μ΄ν•΄ν•˜μ§€ λͺ»ν•©λ‹ˆλ‹€.

μœ„μ˜ 예제의 전체 버전은 λ‹€μŒκ³Ό κ°™μŠ΅λ‹ˆλ‹€.

https://github.com/acdlite/redux-react-router/blob/master/README.md#bonus -reacting-to-state-changes-with-redux-rx

@pburtchaell 이 ν•΄λ‹Ή μ½”λ“œμ˜ 비동기 버전을 μ‚¬μš©ν•˜μ—¬ REST 호좜 λ“±μ—μ„œ 데이터λ₯Ό κ°€μ Έμ˜¬ 것이라고 κ°€μ •ν•©λ‹ˆλ‹€. λ‚΄κ°€ ν™•μ‹€ν•˜μ§€ μ•Šμ€ 것은 λ¬΄μ—‡μž…λ‹ˆκΉŒ? 그런 λ‹€μŒ μƒμ μœΌλ‘œ μ΄λ™ν•œλ‹€κ³  κ°€μ •ν•˜μ§€λ§Œ ν•΄λ‹Ή 상점은

<strong i="7">@connect</strong>

μ•ˆμœΌλ‘œ, λ§ν•˜μž

<Comments />

μ–΄λ–€ 것이 이미 commentStore에 'μ—°κ²°'(ꡬ독)λ˜μ–΄ μžˆμŠ΅λ‹ˆκΉŒ? λ˜λŠ” μ΄λŸ¬ν•œ μœ„μΉ˜ μž‘μ—…μ„ commentsStore에 λ“±λ‘ν•˜λ©΄λ©λ‹ˆλ‹€.

λ‹€μŒκ³Ό 같은 URL

/comments/123

항상 주석 ꡬ성 μš”μ†Œμ— 'κ²°ν•©'λ˜λ―€λ‘œ μ–΄λ–»κ²Œ μž¬μ‚¬μš©ν•©λ‹ˆκΉŒ? 이것이 λ©μ²­ν•œ 경우 μ£„μ†‘ν•©λ‹ˆλ‹€. μ—¬κΈ°μ—μ„œ 맀우 ν˜Όλž€ μŠ€λŸ½μŠ΅λ‹ˆλ‹€. λ‚΄κ°€ 찾을 μˆ˜μžˆλŠ” ν™•μ‹€ν•œ μ˜ˆκ°€ μžˆμ—ˆλ‹€.

λ‚˜λŠ” λ˜ν•œ 이것과 μ”¨λ¦„ν•˜λ©΄μ„œ λ‚΄ 정적 fetchData(dispatch, params) λ©”μ„œλ“œλ₯Ό ν˜ΈμΆœν•˜λŠ” 방법을 μ•Œμ•„ λ‚΄κ³  μžˆμŠ΅λ‹ˆλ‹€ (정적, μ„œλ²„κ°€ 초기 λ Œλ”λ§ 전에 비동기 FETCH μž‘μ—…μ„ μ „λ‹¬ν•˜κΈ° μœ„ν•΄ ν˜ΈμΆœν•˜κΈ° λ•Œλ¬Έμž…λ‹ˆλ‹€).

μ»¨ν…μŠ€νŠΈ 내에 dispatch λŒ€ν•œ μ°Έμ‘°κ°€ μ‘΄μž¬ν•˜κΈ° λ•Œλ¬Έμ— fetchData 의 ν΄λΌμ΄μ–ΈνŠΈ μΈ‘ ν˜ΈμΆœμ„ μœ„ν•΄ 이것을 μ–»λŠ” κ°€μž₯ κΉ¨λ—ν•œ 방법은 λ‹€μŒμ„ ν˜ΈμΆœν•˜λŠ” Connector 와 μœ μ‚¬ν•œ ꡬ성 μš”μ†ŒλΌκ³  μƒκ°ν•©λ‹ˆλ‹€. fetchData λ˜λŠ” shouldFetchData λ˜λŠ” select 콜백이 dispatch 와 ν•¨κ»˜ state dispatch λŒ€ν•œ μ°Έμ‘°λ₯Ό κ°€μ Έ μ™€μ„œ ν˜„μž¬ store 및 ν•„μš”μ— 따라 FETCH μž‘μ—…μ„ μ „λ‹¬ν•©λ‹ˆλ‹€.

ν›„μžλŠ” 더 κ°„κ²°ν•˜μ§€λ§Œ select λŠ” μˆœμˆ˜ν•œ ν•¨μˆ˜λ‘œ μœ μ§€λ˜μ–΄μ•Όν•œλ‹€λŠ” 사싀을 κΉ¨λœ¨λ¦½λ‹ˆλ‹€. μ „μžλ₯Ό μ‚΄νŽ΄ λ³΄κ² μŠ΅λ‹ˆλ‹€.

λ‚΄ μ†”λ£¨μ…˜μ€ λ‚΄ 섀정에 맞게 μ‘°μ •λ˜μ—ˆμ§€λ§Œ (비동기 _FETCH μž‘μ—…μ„ μ „λ‹¬ν•˜λŠ” 정적 fetchData(dispatch, state) λ©”μ„œλ“œ) μ μ ˆν•œ 속성을 μ‚¬μš©ν•˜μ—¬ 전달 된 λͺ¨λ“  μ½œλ°±μ„ ν˜ΈμΆœν•©λ‹ˆλ‹€. https : // gist.github.com/grrowl/6cca2162e468891d8128 β€”

λ¬Έμ„œλ₯Ό μΆ”κ°€ν•΄μ•Όν•©λ‹ˆλ‹€! "λ°˜μ‘ λΌμš°ν„°μ™€ ν•¨κ»˜ μ‚¬μš©"μ„Ήμ…˜μ—μ„œ κ°€λŠ₯ν•©λ‹ˆλ‹€.

1.0 릴리슀 이후에 곡식적인 방법이 μžˆμŠ΅λ‹ˆλ‹€.

@gaearon을 λ“£κ³  λ°˜κ°‘μŠ΅λ‹ˆλ‹€.

그런 λ‹€μŒ νŠΉμ • μƒνƒœ 변경을 κ΅¬λ…ν•˜κΈ° μœ„ν•΄ κ΄€μ°° κ°€λŠ₯ν•œ μ—°μ‚°μžλ₯Ό μ‚¬μš©ν•˜λ©΄λ©λ‹ˆλ‹€.

λ‚΄ 맀μž₯을 경둜 λ³€κ²½κ³Ό 동기화 μƒνƒœλ‘œ μœ μ§€ν•˜κΈ° μœ„ν•΄ κ΄€μ°° κ°€λŠ₯ν•œ μŠ€νŠΈλ¦Όμ„ μ„€μ •ν–ˆκ³  λ‚΄ 맀μž₯을 μ‹œμ²­ν•  μˆ˜μžˆλŠ” 슀트림 섀정도 μžˆμŠ΅λ‹ˆλ‹€. λ‚΄ μŠ€ν† μ–΄μ—μ„œ 값이 λ³€κ²½ 될 λ•Œ, 특히 λ‚΄ μ•±μ˜ λ‹€λ₯Έ κ³³μ—μ„œ 양식을 μ„±κ³΅μ μœΌλ‘œ 제좜 ν•œ κ²°κ³Ό undefined μ—μ„œ μœ νš¨ν•œ λ¬Έμžμ—΄λ‘œ λ³€κ²½ 될 λ•Œ μƒˆ 경둜둜 μ „ν™˜ν•˜λŠ” 데 관심이 μžˆμŠ΅λ‹ˆλ‹€.

두 슀트림이 μ„€μ •λ˜κ³  μž‘λ™ν•˜λ©° μ €μž₯μ†Œκ°€ μ—…λ°μ΄νŠΈλ˜κ³  μžˆμ§€λ§Œ Rxλ₯Ό 처음 μ‚¬μš©ν•˜κ³  κ΄€μ°° κ°€λŠ₯ν•œ 쿼리에 λ¬Έμ œκ°€ μžˆμŠ΅λ‹ˆλ‹€ ... 포인터가 μžˆμŠ΅λ‹ˆκΉŒ? λ‚΄κ°€ μ˜¬λ°”λ₯Έ 길을 κ°€κ³  μžˆλŠ”κ°€? distinctUntilChanged μžˆμ§€λ§Œ ν˜„μž¬ 제 ꡭ수λ₯Ό κ΅½κ³  μžˆμŠ΅λ‹ˆλ‹€. μ–΄λ–€ 도움을 μ£Όμ…”μ„œ κ°μ‚¬ν•©λ‹ˆλ‹€. :)

νŽΈμ§‘ : μ•Œμ•˜μ–΄! μ£„μ†‘ν•©λ‹ˆλ‹€. 제 μ§ˆλ¬Έμ— λ‹΅ν–ˆμŠ΅λ‹ˆλ‹€. μ•„λž˜μ˜ μ˜μ‚¬ μ½”λ“œ. λ¬΄μ„­κ²Œ 보이면 μ•Œλ €μ£Όμ„Έμš”?

const didChangeProject$ = state$
  .distinctUntilChanged(state => state.project._id)
  .filter(state => typeof state.project._id !== 'undefined');

# 177에 μ°¬μ„±ν•˜μ—¬ 마무리. λΌμš°νŒ…μ„ λ¬Έμ„œν™” ν•  λ•Œ μƒνƒœ λ³€κ²½μ‹œ λ¦¬λ””λ ‰μ…˜, μš”μ²­ μ½œλ°±μ‹œ λ¦¬λ””λ ‰μ…˜ λ“± λͺ¨λ“  μ‹œλ‚˜λ¦¬μ˜€λ₯Ό λ‹€λ£¨μ–΄μ•Όν•©λ‹ˆλ‹€.

λ‚˜λŠ” 이것이 λ‹«ν˜”λ‹€λŠ” 것을 μ•Œκ³ μžˆλ‹€. κ·ΈλŸ¬λ‚˜ React 0.14와 베타 λ²„μ „μ˜ λ‹€μ–‘ν•œ 1.0 μ˜μ‘΄μ„±μœΌλ‘œ 이것에 λŒ€ν•œ μ—…λ°μ΄νŠΈκ°€ 있고 그렇지 μ•Šλ‹€λ©΄ React 0.14, react-router, redux λ“±μ˜ μƒˆλ‘œμš΄ κΈ°λŠ₯에 λŒ€ν•œ νŠœν† λ¦¬μ–Όμ΄ 될 수 μžˆμŠ΅λ‹ˆλ‹€. μ“΄? 이 λͺ¨λ“  것을 λ™μ‹œμ— 배우고 μ΄ν•΄ν•˜λ©΄μ„œ λ‹€κ°€μ˜€λŠ” λ³€κ²½ 사항에 λŒ€ν•œ μ΅œμ‹  정보λ₯Ό μœ μ§€ν•˜λ €λŠ” λ§Žμ€ μ‚¬λžŒλ“€μ΄μžˆλŠ” 것 κ°™μŠ΅λ‹ˆλ‹€. λ‚˜λŠ” 상황이 μœ λ™μ μ΄λΌλŠ” 것을 μ•Œκ³  μžˆμ§€λ§Œ (말μž₯λ‚œ .. μ–΄ .. μ˜λ„ν•˜μ§€ μ•Šμ€) λ‹€λ₯Έ μ˜ˆμ œμ—μ„œ μ„œλ‘œ 잘 μ–΄μšΈλ¦¬μ§€ μ•ŠλŠ” μ‘°κ°μ„λ³΄κ³ μžˆλŠ” 것 κ°™μŠ΅λ‹ˆλ‹€. 그리고 λ©°μΉ  후에도 μ—…λ°μ΄νŠΈ 된 앱을 μž‘λ™μ‹œν‚¬ 수 μ—†μŠ΅λ‹ˆλ‹€. λΌμš°νŒ…. 이 λͺ¨λ“  것이 μ–΄λ–»κ²Œ μž‘λ™ν•˜λŠ”μ§€ μ΄ν•΄ν•˜λŠ” 데 μ—¬μ „νžˆ 어렀움을 κ²ͺκ³  있기 λ•Œλ¬Έμ— λ‚΄ 잘λͺ» 일 κ°€λŠ₯성이 λ†’μœΌλ©° μ΅œμ‹  ν•­λͺ©μœΌλ‘œ μ—…λ°μ΄νŠΈ 된 νŠœν† λ¦¬μ–Όμ΄ 곧 λ‚˜μ˜¬ κ²ƒμœΌλ‘œ κΈ°λŒ€ν•©λ‹ˆλ‹€.

νŠœν† λ¦¬μ–Όμ΄μžˆμ„ λ•ŒκΉŒμ§€ λΌμš°νŒ…μ΄μžˆλŠ” examples/real-world λ₯Ό 자유둭게 μ‚΄νŽ΄λ³΄μ‹­μ‹œμ˜€. μ§€κΈˆμ€ "μ΅œμ‹  및 졜고"λŠ” μ•„λ‹ˆμ§€λ§Œ 잘 μž‘λ™ν•©λ‹ˆλ‹€.

이 νŽ˜μ΄μ§€κ°€ 도움이 λ˜μ—ˆλ‚˜μš”?
0 / 5 - 0 λ“±κΈ‰