Application React (portail)
Sommaire |
React est une librairie javascript utilisée pour développer des interfaces utilisateurs.
Si vous souhaitez utiliser React dans une application html suivez les recommandations suivantes :
- Configurez votre service 1000 pour permettre le développement de l'application
- Créez une application html dans Sage FRP 1000
- Créez un projet React.
- Configurez le projet React.
Environnement
Environnement de développement
L'environnement de développement comprend deux éléments :
- L'environnement de développement React dans lequel vous pouvez réaliser une grande partie des développements.
- L'environnement de développement Sage FRP 1000 utilisé pour développer les APIs utilisées par votre application html.
Environnement de production
Lorsque votre développement est terminé vous pouvez générer un projet statique React qui sera le contenu de votre application html.
Les différences entre l'environnement de développement et le projet statique de production sont les suivantes :
- L'environnement de développement utilise des URLs absolue pour accéder aux APIs 1000, l'environnement de production utilise des URLs relatives.
- L'environnement de développement utilise un jeton d'authentification pour s'identifier auprès de Sage FRP 1000, l'environnement de production utilise les cookies de session de l'application hôte Sage FRP 1000.
Pour configurez les environnements de développement et de production utilisez les fichiers d'environnement de React et des variables d'environnement pour définir les schémas d'URLs et le token d'authentification.
Création des projets
Création de l'application html
Dans le concepteur de modèle créer une application html en choisissant n'importe quel template. Celui-ci sera remplacé par la suite et n'a donc pas d'importance.
Création du projet React
Créer le projet React en utilisant les outils et bonne pratiques standard de React, ce projet doit être placé dans un répertoire différent du répertoire de déploiement de l'application html de Sage FRP 1000.
Configuration
Configuration de l'application Desktop
Vous pouvez utiliser le serveur HTTP de développement de l'application Desktop pour tester votre projet React.
Pour cela, dans le concepteur de modèle :
- Déployer les applications mobiles
- Démarrez le serveur HTTP
Configurez ensuite l'application React pour utilisez l'adresse du serveur de développement (http://localhost:8080/sdata/)
Configuration du service 1000
Vous pouvez utiliser un service 1000 pour tester et valider vos développement.
Pour permettre à l'application React en cours de développement d'accéder aux APIs Sage FRP 1000 il est nécessaire d'autoriser les accès cross-origin.
Dans le fichier de configuration du service 1000 :
... HTTP CORS Allow origin=* ...
Générez un token d'authentification pour le dossier et l'application Sage FRP 1000 dans laquelle vous développez.
Tip : Ces paramétrages ne sont pas nécessaires sur un service Sage FRP 1000 de production, ils sont utilisés uniquement en développement |
Configuration du projet React
Modification pour générer une application relative à index.html
Cette modification permet de générer un site statique de production relatif au fichier index.html.
Dans package.json ajouter la variable homepage = ".'
{ "name": "myapp", "version": "0.1.0", "private": true, "homepage": ".", "dependencies": .... .... }
Modification pour copier l'application statique dans le dossier de l'application html de FRP 1000
Cette modification permet de copier le site statique de production dans le dossier de déploiement de l'application html de Sage FRP 1000.
Modifier package.json en ajoutant une section postbuild :
{ "name": "myapp", "version": "0.1.0", "private": true, "homepage": ".", ... "scripts": { "start": "react-scripts start", "build": "react-scripts build", "postbuild": "cp -r -f ./build/* /c/LocalSite900/htmls/testreact", "test": "react-scripts test", "eject": "react-scripts eject" }, ... }
Tip : La syntaxe précédente correspond à l'utilisation de bash, si vous utilisez le terminal Windows modifiez l'ordre de copie en conséquence. |
Modification pour gérer des variables d'environnement pour configurer l'application
Créer un fichier ".env.development" et un fichier ".env.production" à la racine de l'application React
REACT_APP_NAME=Sage FRP 1000 (development) REACT_APP_API_URL=https://localhost/sdata/ REACT_APP_API_PACKAGE=testreactpackage REACT_APP_API_TOKEN=1000...BD0D5CBA4F4864AFA7
REACT_APP_NOT_SECRET_CODE=Sage FRP 1000 (production) REACT_APP_API_URL=../../server/sdata/ REACT_APP_API_PACKAGE=testreactpackage
Tip : Ces variables correspondent à l'utilisation de la librairie ApiFetch.js qui encapsule l'appel à la fonction fetch() de javascritpt, voir ci-dessous |
Tip : L'url de l'API (REACT_APP_API_URL) dépend si vous développez en utilisant le serveur de développement de l'application Desktop ou un service 1000 |
Appel des APIs Sage FRP 1000 à partir des composants React
La méthode traditionnelle consiste à utiliser des appels REST via la librairie javascript fetch() dans la méthode componentDidMount() des composants React.
Pour tenir compte de la différence entre l'environnement de développement et l'environnement de production, vous pouvez encapsuler l'appel à fetch() pour prendre en compte de façon transparente ces différences.
Par exemple, voici une encapsulation de la fonction fetch() qui permet de gérer les appels aux APIs Sage FRP 1000 :
//Credit //better-fetch from Swizec //[email protected] //http://swizec.com //https://github.com/Swizec/better-fetch var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }(); var _includeTrailingUrlSeparator = function(s) { if (s.substr(-1) !== '/') return s + '/'; else return s; }; var apiConfiguration = {url:'', package:'', headers:{'Content-Type': 'application/json'} }; var apiFetch = function apiFetch(methodName) { var params = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; params.headers = Object.assign({}, headerDict(params.headers), apiConfiguration.headers); params.credentials = 'same-origin'; params.method = 'POST'; var aurl = apiConfiguration.url; if (methodName.indexOf('/') > -1) aurl = aurl+methodName; else aurl = aurl+apiConfiguration.package+'/'+methodName; return fetch(aurl, params); }; var headerDict = function headerDict(headers) { var dict = {}; if (headers instanceof Headers) { var _iteratorNormalCompletion = true; var _didIteratorError = false; var _iteratorError = undefined; try { for (var _iterator = headers.entries()[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { var _step$value = _slicedToArray(_step.value, 2), key = _step$value[0], value = _step$value[1]; dict[key] = value; } } catch (err) { _didIteratorError = true; _iteratorError = err; } finally { try { if (!_iteratorNormalCompletion && _iterator.return) { _iterator.return(); } } finally { if (_didIteratorError) { throw _iteratorError; } } } } else { dict = headers; } return dict; }; apiFetch.setUrl = function (url) { apiConfiguration.url = url; }; apiFetch.setDefaultHeaders = function (headers) { apiConfiguration.headers = headerDict(headers); }; apiFetch.throwErrors = function (response) { if (!response.ok) { var err = new Error(response.statusText); err.response = response; throw err; } return response; }; apiFetch.initializeFromEnv = function() { // REACT_APP_API_URL // // In development mode: // must be the absolute url to the service // ex : https://myhost/sdata/ // // In production mode // must be the relative path // ex : ../../server/sdata // REACT_APP_API_PACKAGE // // should be the default package name used for this app // If the call doesn't include a package name this package is used. // REACT_APP_API_TOKEN // // Use only in development mode // must be a valid authentication token apiConfiguration.url = _includeTrailingUrlSeparator(process.env.REACT_APP_API_URL); apiConfiguration.package = process.env.REACT_APP_API_PACKAGE; if (process.env.NODE_ENV === 'development') { apiConfiguration.headers['Authorization'] = 'Bearer '+ process.env.REACT_APP_API_TOKEN; }; //console.log('api headers',apiConfiguration.headers); }; module.exports = apiFetch;
Cette librairie doit être configurée par un appel à initializeFromEnv() dans le fichier index.js de l'application React :
import React from 'react'; import ReactDOM from 'react-dom'; import './index.css'; import App from './App'; import * as serviceWorker from './serviceWorker'; import fetch from './ApiFetch.js' fetch.initializeFromEnv(); ReactDOM.render( <React.StrictMode> <App /> </React.StrictMode>, document.getElementById('root') ); // If you want your app to work offline and load faster, you can change // unregister() to register() below. Note this comes with some pitfalls. // Learn more about service workers: https://bit.ly/CRA-PWA serviceWorker.unregister();
Dans un composant React importez simplement cette librairie et appelez fetch() :
Ici le composant appel la fonction getData() du paquet par défaut défini dans les fichiers d'environnement.
import React, { Component } from 'react'; import fetch from './ApiFetch.js' class App extends Component { state = { data: [] }; componentDidMount() { fetch('getdata') .then(result => result.json()) .then(result => { this.setState({ data: result.agencies }) }); } render() { const { data } = this.state; console.log(data); const result = data.map((entry, index) => { console.log(entry); return <li key={entry.id}>{entry.city}</li>; }); return <div className="container"><ul>{result}</ul></div>; } } export default App;
Voir aussi :