<> = react = https://reactjs.org/ https://react.dev/ A [[Javascript]] library for building user interfaces. Build encapsulated components that manage their own state, then compose them to make complex UIs. https://reactjs.org/docs/thinking-in-react.html The main component react methods are: * render * componentWillUnmount * componentDidMount We can set XML node properties for the component and properties for its inner state. The component also allow inner children. '''Structure''' {{{#!highlight bash . ├── App.tsx ├── build.sh ├── greeter.html ├── greeter.tsx ├── lib.ts ├── NameHolder.tsx ├── package.json ├── tsconfig.json └── webpack.config.js }}} == webpack.config.js == {{{#!highlight javascript var path = require('path'); module.exports = { entry: {main:'./greeter.js'}, resolve: { extensions: ['.js', '.jsx', '.ts', '.tsx'] }, output: { filename: 'bundle.js', path: path.resolve(__dirname, 'dist') } }; }}} == tsconfig.json == {{{#!highlight javascript { "compilerOptions": { "module": "es2015", "target": "es5", "noImplicitAny": true, "removeComments": true, "preserveConstEnums": true, "sourceMap": true, "moduleResolution": "node", "allowSyntheticDefaultImports": true, "jsx": "react" } } }}} == lib.ts == {{{#!highlight javascript function getText() { return "text"; } interface Person { firstName: string; lastName: string; } function greeterPerson(p: Person) { return "Hello GP, " + p.firstName + ' ' + p.lastName + ' ' + getText(); } function greeter(person: string) { return "Hello, " + person; } interface HumanInterface { name: string; getName(): void; } class Human implements HumanInterface { name: string; constructor(name: string) { this.name = name; } getName() { return "My name is " + this.name; } } class PubSub { callbacks: Function[]; constructor() { this.callbacks = []; } addListener(fn: Function): void { this.callbacks.push(fn); } notify(message: string): void { this.callbacks.forEach((fn) => { fn(message); }); } } let pubSub = new PubSub(); export { greeter, greeterPerson, Human, HumanInterface, Person, getText, PubSub, pubSub } }}} == greeter.html == {{{#!highlight html React + typescript test
}}} == package.json == {{{#!highlight javascript { "name": "test", "private": true, "version": "0.0.0", "devDependencies": { "@types/react": "15.0.35", "@types/react-dom": "15.5.1", "@types/webpack-env": "1.13.0", "react": "15.6.1", "react-dom": "15.6.1", "typescript": "2.4.1", "webpack": "2.5.1" } } }}} == App.tsx == {{{#!highlight javascript import React, { ReactChild } from 'react'; import { Persn, greeterPerson, Human, HumanInterface } from './lib'; import NameHolder from './NameHolder'; import { pubSub } from './lib'; interface MyState { currDate: string; greetings: string; human: HumanInterface; } function createMyState(currDate: string, greetings: string, human: HumanInterface): MyState { return { currDate: currDate, greetings: greetings, human: human }; } interface MyProps { prop: string; } export default class App extends React.Component { text: string; timerID: number; constructor(props: MyProps) { super(props); this.text = this.props.prop; this.state = createMyState("waiting for date", "waiting for greetings", null); // init with MyState format } public static createHuman(name: string): HumanInterface { return new Human(name); } public tickHandler() { let cd = new Date().toString(); let greetings = greeterPerson({ firstName: "first", lastName: "last" }); let human: HumanInterface = App.createHuman("JohnDoe"); this.setState(createMyState(cd, greetings, human)); } componentDidMount() { // called after the 1st render ! console.log("First render"); this.timerID = setInterval(this.tickHandler.bind(this), 1000); } componentWillUnmount() { // component will be destroyed console.log("Will be destroyed soon"); clearInterval(this.timerID); } public render() { // do not call set state in render ! return (

Hello World!!! -- {this.text} -- {this.state.greetings}

Human {this.state.human != null ? this.state.human.getName() : ""} {this.state.currDate}

{ this.clickHandler(); }} > {this.props.children}
); } public clickHandler() { console.log("clicked. # children " + React.Children.count(this.props.children)); React.Children.forEach(this.props.children, (argx: any) => { if (argx.hasOwnProperty("props")) { console.log("props property found"); pubSub.notify("message from outer space !"); } console.log(JSON.stringify(argx)); }); } } }}} == greeter.tsx == {{{#!highlight javascript import React from 'react'; import ReactDOM from 'react-dom'; import {getText} from "./lib"; import App from './App'; // uses App.tsx import NameHolder from './NameHolder'; console.log("Entry point"); let appContainer = document.getElementById('app') ; let markup = ; ReactDOM.render( markup , appContainer); }}} == NameHolder.tsx == {{{#!highlight javascript import React from 'react'; import { pubSub } from './lib'; // Component properties (XML attributes) interface NameHolderProperties { attr: string; } interface NameHolderState { attr: string; } // properties and state export default class NameHolder extends React.Component { constructor(props: NameHolderProperties) { super(props); // populates the this.props this.state = { attr: this.props.attr }; pubSub.addListener(this.onMessage); } public render() { return !!!{this.state.attr}!!!; } public onMessage(message: string): void { console.log(this.state.attr + " receiVed " + message); } } }}} == build.sh == {{{#!highlight bash PATH=$PATH:./node_modules/typescript/bin echo Delete dist folder rm -rf dist echo Install NPM packages npm install echo Compile project tsc echo Create application bundle nodejs ./node_modules/webpack/bin/webpack.js --config webpack.config.js }}} == TypeDI == * https://www.npmjs.com/package/typedi TypeDI is a dependency injection tool for TypeScript and JavaScript. With it you can build well-structured and easily testable applications in Node or in the browser. {{{#!highlight javascript import { Container, Service } from 'typedi'; @Service() class ExampleInjectedService { printMessage() { console.log('I am alive!'); } } @Service() class ExampleService { constructor( // because we annotated ExampleInjectedService with the @Service() // decorator TypeDI will automatically inject an instance of // ExampleInjectedService here when the ExampleService class is requested // from TypeDI. private injectedService: ExampleInjectedService ) {} } const serviceInstance = Container.get(ExampleService); // we request an instance of ExampleService from TypeDI serviceInstance.injectedService.printMessage(); // logs "I am alive!" to the console }}} == axios == * https://www.npmjs.com/package/axios Promise based HTTP client for the browser and node.js {{{#!highlight javascript import axios from 'axios'; //const axios = require('axios'); // legacy way try { const response = await axios.get('/user?ID=12345'); console.log(response); } catch (error) { console.error(error); } // Optionally the request above could also be done as axios .get('/user', { params: { ID: 12345, }, timeout: 5000, // 5 seconds. See "Handling Timeouts" below for matching error handling }) .then(function (response) { console.log(response); }) .catch(function (error) { console.log(error); }) .finally(function () { // always executed }); // Want to use async/await? Add the `async` keyword to your outer function/method. async function getUser() { try { // Example: GET request with query parameters const response = await axios.get('/user', { params: { ID: 12345, }, }); // Using the `params` option improves readability and automatically formats query strings console.log(response); } catch (error) { console.error(error); } } }}} == tsoa == * https://www.npmjs.com/package/tsoa OpenAPI-compliant REST APIs using [[typescript]] and Node * https://tsoa-community.github.io/docs/getting-started.html