Dog foot print

[React, 라이브러리]Connected React Router 본문

REACT

[React, 라이브러리]Connected React Router

개 발자국 2019. 8. 12. 23:41

React-router가 v4,v5로 업데이트되면서 기존 react-router-redux 에서 connected-react-router로 변경되었다. 

 

Connected React Router란 

리덕스에서 주소를 변경 및 확인하기 위해 history객체를 관리하며 필요에 의해 꺼내쓸 수 있는 유용한 라이브러리이다. 

 

깃헙 readme를 읽어 보니 기능은 다음과 같다. 

 

  • 단방향 흐름을 통해 리덕스에서 router상태를 동기화 할 수 있다. (history객체 -> store-> router-> component)
  • react Router 버전 v4, v5를 지원한다. 
  • 함수형 컴포넌트를 지원한다. 
  • redux-thunk나 redux-saga를 통해 히스토리 객체를 디스패치할 수 있다. 
  • immutable.js를 지원한다. 
  • TypeScript 를 지원한다. 

//redux-thunk, redux-saga는 redux의 미들웨어로서 스토어에서 액션 뿐만 아니라 함수를 디스패치 할 수 있도록 도와준다. 

 

설치

npm

$ npm install --save connected-react-router

 

yarn 

$ yarn add connected-react-router

 

하위컴포넌트에서 바로 히스토리객체 사용하기 

 

connected-react-router와 react-router, redux-thunk, redux를 설치 한 후 진행 합니다. 

 

store를 정의하는 store.js를 만들고 다음과 같이 store를 정의 합니다. 중요한 것은 router 리듀서명은 router로 고정해야합니다.

 

//라이브러리
import { createStore, applyMiddleware } from 'redux';
import { connectRouter, routerMiddleware } from 'connected-react-router';
//리듀서

export function configureStore(history){

    return createStore(
        combineReducers({
            router : connectRouter(history)
        }),
        applyMiddleware(routerMiddleware(history))
    )
}

 

 

다음 Root 파일인 index.js 에서 history객체를 불러옵니다. history는 history모듈에서 createBrowserHistory로 받아올 수 있습니다 .

 

connectedRouter객체를 C-R-R에서 받아오고 Provide-connectedRouter-App 순으로 감쌉니다. 

 

import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import { Provider } from 'react-redux';
import { createBrowserHistory } from 'history';
import { ConnectedRouter } from 'connected-react-router';
import { configureStore } from './store';

const history = createBrowserHistory(); //히스토리 객체 반환
const store = configureStore(history);

ReactDOM.render(
    <Provider store={store}>
        <ConnectedRouter history={history}>
            <App />
        </ConnectedRouter>
    </Provider>
, document.getElementById('root'));

 

위와 같이 provider 와 connectedRouter로 컴포넌트를 감싸면 해당 컴포넌트에서는 바로 history객체를 받아서 사용할 수 있다. 

 

시험을 위해 App.js에서 Route를 나눠주고 history객체에 push메서드를 사용하니 해당 url로 이동하는 것을 볼 수 있다. 

 

import React, { Component } from 'react'
import {Route} from 'react-router';
import { connect } from 'react-redux';
import { withRouter } from 'react-router-dom';

class App extends Component {
  
  goToHome = ()=>{
    this.props.history.push("/");
  }

  goToExplain = () =>{
    this.props.history.push("/explain")
  }
  render() {
    return (
      <div>
       <span onClick={this.goToHome}>홈으로</span>
       <span onClick={this.goToExplain}>설명으로</span>
       <Route exact path="/" component={Home}/>
       <Route path="/explain" component={Explain}/>
      </div>
    )
  }
}

class Home extends Component {
  render(){
    return (
      <div>
        안녕하세요 여기는 / 입니다.
      </div>
    )
  }
}

class Explain extends Component {
  render(){
    return (
      <div>
        여기는 explain 입니다.
      </div>
    )
  }
}

export default connect(null,null)(withRouter(App))

 

 goBack이라는 메서드를 사용하면 바로 전 url로 이동합니다. 

 

 goBack = () => {
    this.props.history.goBack();
  }
  
  

 

Redux-thunk로 push메서드 dispatch하기 

글을 쓰고 저장이 되어 addArticleSuccess를 디스패치 한 다음 list가 있는 url로 가고 싶을 때 간단하게 C-R-R에서 push메서드를 가져와 디스패치 할 수 있다. 

 

import { push } from 'connected-react-router';

const addArticleRequest = createAction(types.ADD_ARTICLE_REQUEST);
const addArticleSuccess = createAction(types.ADD_ARTICLE_SUCCESS);
const addArticleFailed = createAction(types.ADD_ARTICLE_FAILED);

export const addArticle = (whereCollection,title,content,file) =>{
    return (dispatch,getState) =>{
        dispatch(addArticleRequest());

        const state = getState();        
        const userId = state.auth.user.uid;
        const userDisplayName = state.auth.user.displayName;
        const userProfileUrl = state.auth.user.photoURL;
        //getState를 쓰면 현재 스토어의 스테이트를 알 수 있다. 
        ArticleAPI.addArticle({whereCollection,title,userId,content,file,userDisplayName,userProfileUrl})
        .then(()=>{
            dispatch(addArticleSuccess());
            dispatch(push(`/community/${whereCollection}`));
        }).catch((error)=>{
            dispatch(addArticleFailed(error));
        })
    }
}

 

반응형
Comments