Javascript React

React JS ist eine Javascript Library mit ihrem Ursprung bei Facebook. Mit React JS programmieren Entwickler die Benutzerschnittstellen von Anwendungen wie beim Gutenberg-Editor und PayPal. React kommt in erster Linie in großen Projekten mit großen Teams zum Einsatz.

React JS Symbol

Erste Schritte mit React

Die Einarbeitung und erste Schritte mit REACT brauchen keinen komplizierten Projekt-Ordner. Für den Anfang reicht eine einfache HTML-Datei.

In das body-Tag des HTML-Dokuments kommt ein div mit der ID root.

<div id="root"></div>

Im head-Element der Seite sitzen zwei Script-Tags

<script src="https://unpkg.com/react@16.13.1/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16.13.1/umd/react-dom.development.js"></script>

Die unpkg-Versionen sind nur für ein erstes Ausprobieren – für eine Produktionsumgebung wären sie viel zu schwere Kost. Aber bevor wir uns an das Zusammenstellen und Konfigurieren eines kompletten React-JS-Projekts machen, erzielt dieser Anlauf sofort einen Einblick in das React-Ökosystem.

React Developer Tools

Am besten noch die React-Developer-Tools in Chrome installieren.

react-developer-tools-chrome

Hilfreich: Die React-Developer-Tools für Chrome.

Die React-Developer-Tools setzen das React-Icon in die Browserleiste – z.B. zu sehen bei der Bearbeitung von WordPress-Seiten mit Gutenberg.

react-gutenberg

Während der Entwicklung ist das Icon auf der Testseite zuerst ausgegraut, und dann nach den ersten Ausgaben rot. Erst wenn die Seite in die Produktion umgesetzt wird, wird es blau.

React-Elemente setzen

Ans Ende der Seite, vor dem schließenden body-Tag ein script-Tag für React-Elemente setzen.

<script>
ReactDOM.render ( // https://reactjs.org/docs/react-dom.html
        type: HTML-Element ---+           +--- child
                              |           |
	React.createElement ("h1", null, "Hallo React"),    // https://reactjs.org/docs/react-api.html#createelement
	                            |
	              Properties ---+
	document.getElementById ("root")
);
</script>
<script>
ReactDOM.render (              // https://reactjs.org/docs/react-dom.html
	React.createElement (      // https://reactjs.org/docs/react-dom.html
		"h1",                  type
		null,                  [props]
		"Hallo React"          [...children]
	),
	document.getElementById("root")
);
</script>

Das erzeugt ein HTML-Element, z.B. ein h1, div oder ul. type kann auch eine React-Komponente oder ein React-Fragment sein.

[props], das oben noch als null steht, kann als Objekt eingesetzt werden.

{ "style": {"color": "navy"}}

Verschachtelte Elemente erzeugen

ReactDOM.render (
	React.createElement (
		"div", 
		null, 
		React.createElement (
			"h1",
			null,
			"Wrapped in div"
		)
	),
	document.getElementById("root")
);

So weit sieht das schön strict und einfach aus, aber sobald wir z.B. eine ul-Liste mit einem Dutzend li-Elementen erzeugen, überschwemmen wir das Script mit Massen von React.createElement-Aufrufen.

An dieser Stelle setzt JSX (Javascript as XML) auf: JSX konvertiert HTML-Markup in React.createElement()-Aufrufe.

JSX und Babel

JSX ist eine Syntax, die Tags à la XML direkt einsetzt. Als drittes Script-Tag kommt Babel-standalone in den Head der Seite.

Die render()-Methode der React-Komponenten gibt HTML-Markup als JSX-Syntax zurück. Mit JSX wird das HTML übersichtlich und muss nicht aufwändig von regulärem Javascript erzeugt werden.

render wird aufgerufen, wenn sich Eigenschaften oder der Zustand der Anwendung ändern. render muss etwas zurückgeben. Wenn kein JSX zurückgegeben wird, dann wenigstens null.

<script src="https://unpkg.com/@babel/standalone@7.9.6/babel.min.js"></script>

Damit kann HTML-Markup direkt in ReactDOM.render eingesetzt werden. Aufpassen: Anstelle des einfachen Script-Tags muss jetzt type="text/babel" als Javascript-type-Attribut eingesetzt werden.

<div id="root"></div>

<script type="text/babel">
ReactDOM.render (
	<h1>Hallo React / JSX mit Babel-standalone</h1>,
	document.getElementById("root")
);
</script>

Arbeiten mit JSX-Expressions:

let user = "Emma";

ReactDOM.render (
	<h1>Hallo <span className="header">{user}</span>: React / JSX </h1>,
	document.getElementById("root")
);

HTML verschachteln und HTML-Attribute: Weil class ein reserviertes Wort in Javascript ist, muss anstelle des class-Attributs className eingesetzt werden.

React components

Components – Komponenten – setzen die Benutzerschnittstelle aus unabhängigen und wieder verwertbaren Einzelteilen zusammen. React Components ähneln Javascript-Funktionen. Sie nehmen beliebige Eingaben als Argument (die sogen. props) und geben React-Elemente zurück, die die Ausgabe auf dem Monitor beschreiben.

React Components

Die Namen von Komponenten müssen mit einem Großbuchstaben anfangen.

Anstelle des HTML-Markups in ReactDom.render kommt eine Welcome-Komponente.

<script type="text/babel">
const user = "Emma";
const Welcome = () => <h1>Hallo <span className="header">{user}</span>: React / JSX mit Babel-standalone</h1>

ReactDOM.render (
	<Welcome />,
	document.getElementById("root")
);
</script>

Besser noch: Damit die Funktion besser lesbar wird, HTML-Markup einrücken.

const Welcome = () => {
	return (
		<h1>Hallo 
			<span className="header">{user}</span>
			: React / JSX mit Babel-standalone
		</h1>
	)
};

Wenn das Markup in geschweifte Klammern gesetzt wird, muss die Funktion einen return-Aufruf enthalten.

[props]

props oder Properties (Eigenschaften) sind ein React-Objekt mit Informationen zur Komponente.

const user = "Emma";
const Welcome = (props) => {
	console.log (props.library);
	return (
			<div>
				<h1>Hallo 
					<span className="header">{user}</span>
					: Versuch mal React / JSX 
				</h1>
				<p>{props.message}</p>
			</div>
		)
	};

ReactDOM.render (
	<Welcome library="React" message="Auf ans Werk!"/>,
	document.getElementById("root")
);

Das liefert

Hallo Emma: Versuch mal React / JSX

Auf ans Werk!

Properties können in beliebigen Mengen angelegt werden. Eine React-Komponente kann man sich als eine Art Funktion vorstellen, der man Daten als Argument übergibt, und die ein React Element oder User Interface zurückgibt. Das ist des Pudels Kern von React: Komponenten miteinander kombinieren, um die Benutzerschnittstelle zu konstruieren.

const Tour = ({name}) => <nav>{name}</nav>;
const App = () => (
	<div>
		<Tour name="Von Kamp Lintfort über Geldern nach Kevelaer" />
		<Tour name="Niederrhein: Entlang der Fossa Eugeniana" />
		<Tour name="Von Moers zum Samans Hof" />
	</div>
);

ReactDOM.render (
	<App />,
	document.getElementById("root")
);

Das sind schon zwei Komponenten: Die App-Komponente rendert die Tour-Komponente.

Komponenten als Javascript-Class

<script type="text/babel">
const Tour = ({name}) => <nav>{name}</nav>;
class App extends React.Component {
	render () {
		return (
			<div>
				<Tour name="Von Kamp Lintfort über Geldern nach Kevelaer" />
				<Tour name="Niederrhein: Entlang der Fossa Eugeniana" />
				<Tour name="Von Moers zum Samans Hof" />
				<Tour name="Wesel: Über den Rhein mit der Fähre" />
			</div>
		)
	}
};

ReactDOM.render (
	<App />,
	document.getElementById("root")
);
</script>

React state

Ein weiteres Konzept von React ist State – der Zustand. React-Elemente sind unveränderlich. Sobald ein Element erzeugt wurde, können weder seine Children noch seine Attribute geändert werden. Jedes Element ist wie ein einzelner Frame in einem Video und stellt die Benutzerschnittstelle zu einem bestimmten Zeitpunkt dar (Updating the Rendered Element).

Das state-Objekt ist der Platz, an dem Eigenschaften einer Komponente gespeichert werden. Wenn Daten sich ändern, wird die Render-Funktion erneut aufgerufen, um den geänderten Zustand anzuzeigen.

const Tour = ({name}) => <nav>{name}</nav>;
class App extends React.Component {
	state = {
		finished: false
	}
	
	finishTour = () => this.setState({finished: true})
	repeatTour = () => this.setState({finished: false})
	render () {
		return (
			<div>
				<button onClick={this.finishTour}>Tour abgeschlossen</button> <button onClick={this.repeatTour}>Tour wiederholen</button>
				<div>
					Die Tour ist {
						this.state.finished 
						? "abgeschlossen" 
						: "wird wiederholt"
					}
				</div>
				<Tour name="Von Kamp Lintfort über Geldern nach Kevelaer" />
				<Tour name="Niederrhein: Entlang der Fossa Eugeniana" />
				<Tour name="Mit dem Rad rund um die Xantener Nordsee" />
			</div>
		)
	}
};

ReactDOM.render (
	<App />,
	document.getElementById("root")
);

setState () kann nicht innerhalb der render-Funktion definiert werden, weil setState den Zustand der Anwendung ändert und die Änderung des Zustands die render-Funktion aufruft.

Ein Blick in den Ordner: In der index.html sehen wir jetzt HTML-Markup.

<div id="root"><div>
	<button>Tour abgeschlossen</button> <button>Tour wiederholen</button>
	<div>Die Tour ist wird wiederholt</div>
		<nav>Von Kamp Lintfort über Geldern nach Kevelaer</nav>
		<nav>Niederrhein: Entlang der Fossa Eugeniana</nav>
		<nav>Mit dem Rad rund um die Xantener Nordsee</nav>
	</div>
</div>

Der Begriff state ist vielleicht etwas ungünstig gewählt. Ein Zustand ist die aktuelle Darstellung der App auf dem Monitor. Dieser Zustand kann nicht nur einfach z.B. loading oder error sein, sondern React versteht darunter die Variablen der App, die sich aufgrund einer Aktion ändern können.

State mit Function

Komponente auf anhand einer Bedingung rendern

const Radtour = ({name}) => <p>{name}</p>;
const Wanderung = ({name}) => <p>{name}</p>;

const App = ({fahrrad}) => (
	<div>
		{fahrrad 
			? <Radtour name="Radtour entlang der Fossa Eugeniana" />
			: <Wanderung name="Wanderung um die Xantener Nordsee" />
		}
	</div>
)
	
ReactDOM.render (
	<App fahrrad={false}/>,
	document.getElementById("root")
);

Über Listen iterieren

Listen brauchen einen Key, sonst gibt es eine Warnung

//react.development.js:401 Warning: Each child in a list should have a unique "key" prop.

const tourTarget = ["Fossa Eugeniana", "Xantener Nordsee", "Schloss Dyck"];

const App = ({touren}) => (
	<ul>
		{touren.map ((rad,i) =>
			<li key={i}>{rad}</li>
		)}
	</ul>
)
	
ReactDOM.render (
	<App touren={tourTarget} />,
	document.getElementById("root")
);
//react.development.js:401 Warning: Each child in a list should have a unique "key" prop.

Alternativ: Array of Objects

const tourTarget = [
	{id: 1, name: "Xantener Nordsee", route: "Ab Bahnhof Xanten"},
	{id: 2, name: "Fossa Eugeniana", route: "Ab Bahnhof Rheinberg"},
	{id: 3, name: "Samans Hof", route: "Ab Vluyner Platz"},
];


const App = ({touren}) => (
	<ul>
		{touren.map ((rad,i) =>
			<li key={i}>{rad.name} Start: {rad.route}</li>
		)}
	</ul>
)
	
ReactDOM.render (
	<App touren={tourTarget} />,
	document.getElementById("root")
);
<div id="root">
	<ul>
		<li>Xantener Nordsee Start: Ab Bahnhof Xanten</li>
		<li>Fossa Eugeniana Start: Ab Bahnhof Rheinberg</li>
		<li>Samans Hof Start: Ab Vluyner Platz</li>
	</ul>
</div>

React App veröffentlichen

Bis hierhin ist diese Arbeitsweise effizient für die ersten Schritte. Die Create React-App setzt ein React-Projekt mit allen benötigten Zutaten auf. Die React Create App wird mit NPM installiert, ohne dass dafür Tools wie Webpacke oder Babel installiert und konfiguriert werden müssen.

In den neueren Version von React muss auch die React App selber nicht mehr auf dem Entwicklungssystem installiert werden, sondern npx create-react-app myapp erzeugt den React-Ordner und npm start startet NodeJS mit der Anwendung direkt.

Alternativ: React mit SandCodeBox online

Eine weitere Alternative für die ersten Schritte mit React ist CodeSandBox.io – mit CodeSandBox Online erspart man sich ebenfalls die Installation auf dem eigenen Rechner.

codesandbox
Component props DOM State
Suchen auf mediaevent.de