Recherche…


Introduction

Ce document montre comment utiliser ReactRouter avec Meteor et React. De zéro à une application qui fonctionne, y compris les rôles et l'authentification.

Je vais montrer chaque étape avec un exemple

1- Créer le projet

2- Ajouter React + ReactRouter

3- Ajouter des comptes

4- Paquets de rôles

Créer le projet

1- Tout d’abord, installez https://www.meteor.com/install

2- Créer un projet. ( --bare est de créer un projet vide)

meteor create --bare MyAwesomeProject

3- Créez la structure de fichier minimale ( -p pour créer des répertoires intermédiaires):

cd MyAwesomeProject

mkdir -p client server imports/api imports/ui/{components,layouts,pages} imports/startup/{client,server}

4- Maintenant, créez un fichier HTML dans client / main.html

<head>
   <meta charset="utf-8">
   <title>My Awesome Meteor_React_ReactRouter_Roles App</title>
</head>
 
<body>
  Welcome to my Meteor_React_ReactRouter_Roles app
</body>

5- Assurez-vous que cela fonctionne: (3000 est le port par défaut, vous pouvez donc ignorer le '-p 3000')

meteor run -p 3000

et ouvrez votre navigateur sur 'localhost: 3000'

Remarque:

  • Je saute d'autres fichiers que vous devrez créer pour raccourcir les choses. Plus précisément, vous devrez créer des fichiers index.js dans les répertoires client , imports / startup / {client, serveur} et serveur .

  • Vous pouvez voir un exemple complet dans https://github.com/rafa-lft/Meteor_React_Base . Rechercher le tag Step1_CreateProject

Ajouter React + ReactRouter

Si nécessaire, cd MyAwesomeProject répertoire de votre projet cd MyAwesomeProject

1- Ajouter réagir et réagir au routeur

meteor npm install --save [email protected] [email protected] [email protected]

2- Modifiez client / main.html et remplacez le contenu par:

 <body>
    <div id="react-root"></div>
 </body>

Quoi que le reactRouter décide d'afficher, il le montrera dans l'élément '# react-root'

3- Créer le fichier Layouts dans imports / ui / layouts / App.jsx

import React, { Component } from 'react';
import PropTypes from 'prop-types';


class App extends Component {
  constructor(props) {
    super(props);
  }

  render() {
    return (
      <div>
        {this.props.children}
      </div>
    );
  }
}

App.propTypes = {
  children: PropTypes.node
};

export default App;

4- Créer le fichier Routes dans imports / startup / client / Routes.jsx

import ReactDOM from 'react-dom';
import React, { Component } from 'react';
import { Router, Route, IndexRoute, browserHistory } from 'react-router';

import App from '../../ui/layouts/App.jsx';

import NotFound from '../../ui/pages/NotFound.jsx';
import Index from '../../ui/pages/Index.jsx';


class Routes extends Component {
  constructor(props) {
    super(props);
  }

  render() {
    return (
      <Router history={ browserHistory }>
        <Route path="/" component={ App }>
          <IndexRoute name="index" component={ Index }/>
          <Route path="*" component={ NotFound }/>
        </Route>
      </Router>
    );
  }
}

Routes.propTypes = {};


Meteor.startup(() =>{
  ReactDOM.render(
    <Routes/>,
    document.getElementById('react-root')
  );
});

Remarque:

  • Je saute d'autres fichiers que vous devrez créer pour raccourcir les choses. Plus précisément, vérifiez les importations / ui / pages {Index.jsx, NotFound.jsx}.

  • Vous pouvez voir un exemple complet dans https://github.com/rafa-lft/Meteor_React_Base . Recherchez le tag Step2_ReactRouter

Étape 3 - Ajouter des comptes

Si nécessaire, cd MyAwesomeProject répertoire de votre projet cd MyAwesomeProject

1- Ajouter des packages de comptes: meteor add accounts-base accounts-password react-meteor-data

2- Ajoutez les routes pour vous connecter et vous abonner aux pages de imports / startup / Routes.jsx La méthode render () sera la suivante:

  render() {
    return (
      <Router history={ browserHistory }>
        <Route path="/" component={ App }>
          <IndexRoute name="index" component={ Index }/>
          <Route name="login" path="/login" component={ Login }/>
          <Route name="signup" path="/signup" component={ Signup }/>
          <Route name="users" path="/users" component={ Users }/>
          <Route name="editUser" path="/users/:userId" component={ EditUser }/>
          <Route path="*" component={ NotFound }/>
        </Route>
      </Router>
    );
  }

Remarque:

  • Je saute d'autres fichiers dont vous aurez besoin pour raccourcir les choses. Spécifiquement, vérifiez les importations / startup / server / index.js imports / ui / layouts / {App, NavBar} .jsx et import / ui / pages / {Connexion, Inscription, Utilisateurs, EditUser} .jsx

  • Vous pouvez voir un exemple complet dans https://github.com/rafa-lft/Meteor_React_Base . Rechercher le tag Step3_Accounts

Ajouter des rôles

1- Ajouter un package de rôles ( https://github.com/alanning/meteor-roles)

meteor add alanning:roles

2- Créez des constantes de rôles. Dans le fichier imports / api / accounts / roles.js

const ROLES = {
  ROLE1: 'ROLE1',
  ROLE2: 'ROLE2',
  ADMIN: 'ADMIN'
};

export default ROLES;

3- Je ne montrerai pas comment ajouter / mettre à jour des rôles sur un utilisateur, mais simplement sur le côté serveur, vous pouvez définir des rôles d’utilisateur par Roles.setUserRoles(user.id, roles); Vérifiez plus d'informations dans https://github.com/alanning/meteor-roles et http://alanning.github.io/meteor-roles/classes/Roles.html

4- En supposant que vous avez déjà configuré tous les fichiers de comptes et de rôles (voir exemple complet dans https://github.com/rafa-lft/Meteor_React_Base . Recherchez le tag Step4_roles ), nous pouvons maintenant créer une méthode qui sera chargée d’autoriser ( ou non) accès aux différentes routes. Dans imports / startup / client / Routes.jsx


class Routes extends Component {
  constructor(props) {
    super(props);
  }

  authenticate(roles, nextState, replace) {
    if (!Meteor.loggingIn() && !Meteor.userId()) {
      replace({
        pathname: '/login',
        state: {nextPathname: nextState.location.pathname}
      });
      return;
    }
    if ('*' === roles) { // allow any logged user
      return;
    }
    let rolesArr = roles;
    if (!_.isArray(roles)) {
      rolesArr = [roles];
    }
    // rolesArr = _.union(rolesArr, [ROLES.ADMIN]);// so ADMIN has access to everything
    if (!Roles.userIsInRole(Meteor.userId(), rolesArr)) {
      replace({
        pathname: '/forbidden',
        state: {nextPathname: nextState.location.pathname}
      });
    }
  }

  render() {
    return (
      <Router history={ browserHistory }>
        <Route path="/" component={ App }>
          <IndexRoute name="index" component={ Index }/>
          <Route name="login" path="/login" component={ Login }/>
          <Route name="signup" path="/signup" component={ Signup }/>

          <Route name="users" path="/users" component={ Users }/>

          <Route name="editUser" path="/users/:userId" component={ EditUser }
                 onEnter={_.partial(this.authenticate, ROLES.ADMIN)} />


          {/* ********************
           Below links are there to show Roles authentication usage.
           Note that you can NOT hide them by
           { Meteor.user() && Roles.userIsInRole(Meteor.user(), ROLES.ROLE1) &&
           <Route name=.....
           }
           as doing so will change the Router component on render(), and ReactRouter will complain with:
           Warning: [react-router] You cannot change <Router routes>; it will be ignored

           Instead, you can/should hide them on the NavBar.jsx component... don't worry: if someone tries to access
           them, they will receive the Forbidden.jsx component
           *************/ }
          <Route name="forAnyOne" path="/for_any_one" component={ ForAnyone }/>

          <Route name="forLoggedOnes" path="/for_logged_ones" component={ ForLoggedOnes }
                 onEnter={_.partial(this.authenticate, '*')} />

          <Route name="forAnyRole" path="/for_any_role" component={ ForAnyRole }
                 onEnter={_.partial(this.authenticate, _.keys(ROLES))}/>

          <Route name="forRole1or2" path="/for_role_1_or_2" component={ ForRole1or2 }
                 onEnter={_.partial(this.authenticate, [ROLES.ROLE1, ROLES.ROLE2])} />

          <Route name="forRole1" path="/for_role1" component={ ForRole1 }
                 onEnter={_.partial(this.authenticate, ROLES.ROLE1)}/>

          <Route name="forRole2" path="/for_role2" component={ ForRole2 }
                 onEnter={_.partial(this.authenticate, ROLES.ROLE2)} />


          <Route name="forbidden" path="/forbidden" component={ Forbidden }/>

          <Route path="*" component={ NotFound }/>
        </Route>
      </Router>
    );
  }
}

Nous avons ajouté un déclencheur onEnter à certaines routes. Pour ces routes, nous passons également les rôles autorisés à entrer. Notez que le rappel onEnter reçoit 2 paramètres à l'origine. Nous utilisons des traits de soulignement partiels ( http://underscorejs.org/#partial) , pour en ajouter un autre (rôles) La méthode authenticate (appelée par onEnter) reçoit les rôles et:

  • Vérifiez si l'utilisateur est connecté. Sinon, redirige vers '/ login'.
  • Si rôles === '*', nous supposons que tout utilisateur connecté peut entrer, donc nous l'autorisons
  • Sinon, nous vérifions si l'utilisateur est autorisé (Roles.userIsInRole) et, sinon, nous redirigeons vers interdit.
  • Si vous le souhaitez, vous pouvez décommenter une ligne, ADMIN a donc accès à tout.

Le code contient plusieurs exemples de différents itinéraires autorisés pour quiconque (pas de rappel onEnter), pour tout utilisateur enregistré, pour tout utilisateur connecté avec au moins un rôle et pour des rôles spécifiques.

Notez également que ReactRouter (au moins sur la version 3) ne permet pas de modifier les routes sur Render. Donc, vous ne pouvez pas cacher les routes dans les Routes.jsx. Pour cette raison, nous redirigeons vers / interdit dans la méthode d'authentification.

5- Un bug commun avec ReactRouter et Meteor, concerne les mises à jour de statut d’utilisateur non affichées. Par exemple, l'utilisateur s'est déconnecté, mais nous affichons toujours son nom sur la barre de navigation. Cela se produit parce que Meteor.user () a changé, mais nous ne sommes pas en train de faire un nouveau rendu.

Ce bogue peut être résolu en appelant Meteor.user () dans le createContainer. En voici un exemple, utilisé dans imports / ui / layouts / NavBar.jsx:

export default createContainer((/* {params}*/) =>{
  Meteor.user(); // so we render again in logout or if any change on our User (ie: new roles)
  const loading = !subscription.ready();
  return {subscriptions: [subscription], loading};
}, NavBar);

Remarque:

  • Je saute d'autres fichiers dont vous aurez besoin pour raccourcir les choses. Spécifiquement, vérifiez les importations / startup / server / index.js imports / ui / layouts / {App, NavBar} .jsx et import / ui / pages / {Connexion, Inscription, Utilisateurs, EditUser} .jsx

  • Vous pouvez voir un exemple complet dans https://github.com/rafa-lft/Meteor_React_Base . Recherchez le tag Step4_roles



Modified text is an extract of the original Stack Overflow Documentation
Sous licence CC BY-SA 3.0
Non affilié à Stack Overflow