web-dev-qa-db-fra.com

Ajouter une URL de base à une application utilisant Redux-Router + React-Router

J'utilise React-Router 1.0.0-rc3 avec Redux-Router 1.0.0-beta3.

Lorsque vous utilisez React-Router, vous pouvez utiliser useBasename avec createHistory pour définir l'URL de base d'une application, afin de pouvoir facilement écrire une application s'exécutant dans un sous-répertoire. Exemple :

Au lieu de cela:

import { createHistory } from 'history';

let base = "/app_name/"

<Router history={browserHistory}>
  <Route path={base} component={App}></Route>
</Router>

<Link path={base + "some_path"}>some_path</Link>

Vous pouvez écrire de cette manière en utilisant useBasename:

import { createHistory, useBasename } from 'history';

const browserHistory = useBasename(createHistory)({
  basename: "/app_name"
});

<Router history={browserHistory}>
  <Route path="/" component={App}></Route>
</Router>

<Link path="/some_path">some_path</Link>

Cependant, dans Redux-Router, vous devez passer createHistory au lieu de history à un réducteur:

const store = compose(
  applyMiddleware(m1, m2, m3),
  reduxReactRouter({
    routes,
    createHistory
  }),
  devTools()
)(createStore)(reducer);

Comment pouvons-nous utiliser useBasename dans ce cas?

14
chibicode

Pour react-router v2 ou v3 et utiliser react-router-redux v4 au lieu de redux-router, la configuration de l'objet d'historique ressemblera à ceci:

import { createHistory } from 'history'
import { useRouterHistory } from 'react-router'
import { syncHistoryWithStore } from 'react-router-redux'

const browserHistory = useRouterHistory(createHistory)({
  basename: '<yourBaseUrl>'
})
const history = syncHistoryWithStore(browserHistory, store)

Le reste de la configuration est comme d'habitude lorsqu'il n'y a pas d'URL de base supplémentaire.

12
Diego V

Vous pouvez créer une fonction qui enveloppe useBasename:

const createHistoryWithBasename = (historyOptions) => {
  return useBasename(createHistory)({
    basename: '/app_name',
    ...historyOptions
  })
}

Et passez-le à compose:

const store = compose(
  applyMiddleware(m1, m2, m3),
  reduxReactRouter({
    routes,
    createHistory: createHistoryWithBaseName
  }),
  devTools()
)(createStore)(reducer);
2
chibicode

L'API change très souvent, donc c'est ce qui a fonctionné pour moi (j'utilise la version 2.0.3 de redux-simple-router). J'ai défini l'historique personnalisé dans un fichier séparé:

import { useRouterHistory } from 'react-router'
import { createHistory, useBasename } from 'history'
import { baseUrl } from '../config'

const browserHistory = useRouterHistory(useBasename(createHistory))({
  basename: "/appgen"
});

Maintenant, j'ai besoin d'initialiser le magasin:

import { syncHistory, routeReducer } from 'redux-simple-router'
import browserHistory from '../misc/browserHistory'

const rootReducer = combineReducers({
  // ...other reducers
  routing: routeReducer
});

const reduxRouterMiddleware = syncHistory(browserHistory);

const finalCreateStore = compose(
  // ...other middleware
  applyMiddleware(reduxRouterMiddleware),
)(createStore);


const store = finalCreateStore(rootReducer, initialState);

Finalement, vous devez passer la history à la Router

import browserHistory from './misc/browserHistory'
import routes from '../routes'

export default class Root extends Component {
  static propTypes = {
    history: PropTypes.object.isRequired
  };

  render() {
    return (
      <Router history={browserHistory}>
        {routes}
      </Router>
    )
  }
}

Avant de proposer cela, j'utilisais une solution manual. J'ai défini mon propre composant Link et ma propre action redux responsables de l'ajout de l'URL de base. Cela pourrait être utile pour quelqu'un.

Composant Link mis à jour:

import React, { Component } from 'react'
import { Link as RouterLink } from 'react-router'
import { baseUrl } from '../config'

export default class Link extends Component {
  render() {
    return <RouterLink {...this.props} to={baseUrl + '/' + this.props.to} />
  }
}

Créateur d'action personnalisée:

import { routeActions } from 'redux-simple-router'
import { baseUrl } from '../config'

export function goTo(path) {
  return routeActions.Push(baseUrl + '/' + path);
}

Route racine mise à jour:

import { baseUrl } from './config'
export default (
  <Route component={App} path={baseUrl}>
    //...nested routes
  </Route>
);

Notez que ces outils personnalisés prennent uniquement en charge le repoussage des chemins mis à jour, pas l'objet descripteur location.

1
tobik