Buscar..


Introducción

Este documento mostrará cómo utilizar ReactRouter con Meteor y React. De cero a una aplicación de trabajo, incluyendo roles y autenticación.

Te mostraré cada paso con un ejemplo.

1- Crear el proyecto.

2- Añadir React + ReactRouter

3- Añadir cuentas

4- Añadir paquetes de roles

Crear el proyecto

1- Primero, instale https://www.meteor.com/install

2- Crear un proyecto. ( --bare es crear un proyecto vacío)

meteor create --bare MyAwesomeProject

3- Crea la estructura mínima de archivos ( -p para crear directorios intermedios):

cd MyAwesomeProject

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

4- Ahora, crea un archivo HTML en 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- Asegúrate de que funcione: (3000 es el puerto predeterminado, así que puedes omitir el '-p 3000')

meteor run -p 3000

y abriendo su navegador en 'localhost: 3000'

Nota:

  • Me estoy saltando algunos otros archivos que necesitarás crear para acortar las cosas. Específicamente, deberá crear algunos archivos index.js en los directorios de clientes , importaciones / inicio / {cliente, servidor} y servidor .

  • Puede ver un ejemplo completo en https://github.com/rafa-lft/Meteor_React_Base . Busque la etiqueta Step1_CreateProject

Añadir React + ReactRouter

Si es necesario, cambie al directorio de su proyecto cd MyAwesomeProject

1- Añadir reaccionar y reaccionar-router.

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

2- Editar cliente / main.html, y reemplazar el contenido será:

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

Independientemente de lo que el reactRouter decida mostrar, lo mostrará en el elemento '# react-root'

3- Crea el archivo de diseños en 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- Cree el archivo Rutas en importaciones / inicio / cliente / Rutas.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')
  );
});

Nota:

  • Me estoy saltando algunos otros archivos que necesitarás crear para acortar las cosas. Específicamente, compruebe las importaciones / ui / pages {Index.jsx, NotFound.jsx}.

  • Puede ver un ejemplo completo en https://github.com/rafa-lft/Meteor_React_Base . Busque la etiqueta Step2_ReactRouter

Paso 3- Agregar cuentas

Si es necesario, cambie al directorio de su proyecto cd MyAwesomeProject

1- Agregar paquetes de cuentas: meteor add accounts-base accounts-password react-meteor-data

2- Agregar las rutas para iniciar sesión y las páginas de registro en imports / startup / Routes.jsx El método render () será el siguiente:

  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>
    );
  }

Nota:

  • Me estoy saltando algunos otros archivos que necesitarás, para acortar las cosas. Específicamente, verifique imports / startup / server / index.js imports / ui / layouts / {App, NavBar} .jsx e import / ui / pages / Login, Suscripción, Usuarios, EditUser} .jsx

  • Puede ver un ejemplo completo en https://github.com/rafa-lft/Meteor_React_Base . Busque la etiqueta Step3_Accounts

Agregar roles

1- Agregar paquete de roles ( https://github.com/alanning/meteor-roles)

meteor add alanning:roles

2- Crea algunas constantes de roles. En el archivo imports / api / accounts / roles.js

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

export default ROLES;

3- No mostraré cómo agregar / actualizar roles en un usuario, solo mencionaré que en el lado del servidor, puede establecer roles de usuario mediante Roles.setUserRoles(user.id, roles); Consulte más información en https://github.com/alanning/meteor-roles y http://alanning.github.io/meteor-roles/classes/Roles.html

4- Suponiendo que ya ha configurado todos los archivos de cuentas y roles (vea el ejemplo completo en https://github.com/rafa-lft/Meteor_React_Base . Busque la etiqueta Step4_roles ) ahora podemos crear un método que estará a cargo de permitir ( o no) acceso a las diferentes rutas. En 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>
    );
  }
}

Agregamos un disparador onEnter a algunas rutas. Para esas rutas, también estamos pasando a qué Roles se les permite ingresar. Tenga en cuenta que la devolución de llamada onEnter, recibe 2 parámetros originalmente. Estamos utilizando el subrayado parcial ( http://underscorejs.org/#partial) , para agregar otro (roles). El método de autenticación (llamado por onEnter) recibe los roles y:

  • Compruebe si el usuario ha iniciado sesión en absoluto. Si no, redirige a '/ login'.
  • Si roles === '*' asumimos que cualquier usuario que haya iniciado sesión puede ingresar, así que lo permitimos
  • De lo contrario, verificamos si el usuario tiene permiso (Roles.userIsInRole) y, si no, redirigimos a prohibido.
  • Opcionalmente, puede descomentar una línea, de modo que ADMIN tenga acceso a todo.

El código tiene varios ejemplos de diferentes rutas que están permitidas para cualquier persona (sin devolución de llamada en Entrar), para cualquier usuario registrado, para cualquier usuario registrado con al menos 1 rol y para roles específicos.

También tenga en cuenta que ReactRouter (al menos en la versión 3), no permite modificar las rutas en Render. Así que no puedes ocultar las rutas dentro de Routes.jsx. Por esa razón, redirigimos a / prohibido en el método de autenticación.

5- Un error común con ReactRouter y Meteor, se relaciona con las actualizaciones de estado del usuario que no se muestran. Por ejemplo, el usuario se desconectó, pero aún estamos mostrando su nombre en la barra de navegación. Eso sucede porque Meteor.user () ha cambiado, pero no estamos volviendo a renderizar.

Ese error se puede resolver llamando a Meteor.user () en createContainer. Aquí hay un ejemplo de ello, usado en 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);

Nota:

  • Me estoy saltando algunos otros archivos que necesitarás, para acortar las cosas. Específicamente, verifique imports / startup / server / index.js imports / ui / layouts / {App, NavBar} .jsx e import / ui / pages / Login, Suscripción, Usuarios, EditUser} .jsx

  • Puede ver un ejemplo completo en https://github.com/rafa-lft/Meteor_React_Base . Buscar la etiqueta Step4_roles



Modified text is an extract of the original Stack Overflow Documentation
Licenciado bajo CC BY-SA 3.0
No afiliado a Stack Overflow