217 lines
8.6 KiB
Markdown
217 lines
8.6 KiB
Markdown
+++
|
|
title = "React Notes"
|
|
description = "Basic documentation for React"
|
|
date = 2022-06-22T18:00:00+00:00
|
|
updated = 2022-06-22T18:00:00+00:00
|
|
template = "section.html"
|
|
sort_by = "weight"
|
|
weight = 6
|
|
draft = false
|
|
[taxonomies]
|
|
documentation=["Reference"]
|
|
categories=["React", "single-page-applications"]
|
|
+++
|
|
|
|
[React](https://reactjs.org/) is a Javascript library for creating dynamic and
|
|
responsive websites. It is the most popular of the current generation of SPA
|
|
(Single Page Application) tools, and it's the one I use professionally.
|
|
|
|
## Starting a project
|
|
|
|
React is installed using [npm](https://npmjs.com). You have three principle
|
|
choices when it comes to installing React: You can install it the basic way by
|
|
creating a new project folder and running `npm install react react-dom` (the
|
|
latter is for web-based projects rather than `react-native` projects for Android
|
|
and IOs), you can use a project template (my preferred technique, but it
|
|
requires routine updating), and using
|
|
[create-react-app](https://create-react-app.dev), which includes an entire
|
|
framework for React, including a hot-loader for development, pre-configured
|
|
tooling for ESLint, Prettier, and a host of other code-quality features.
|
|
|
|
Personally, I have always found that create-react-app is limiting in too many
|
|
ways; eventually, I end up not even using the CRA "eject" feature (which
|
|
converts the implicit configuration hidden in the `node_modules` folder into
|
|
explicit configuration); instead, I create a new project, copy the `src` folder
|
|
from the CRA project into that, and construct a new toolchain around it, one
|
|
that isn't cluttered by all the other things found in CRA and one that is
|
|
configured to my exact specficiation.
|
|
|
|
## A Mental Model for React
|
|
|
|
[Caveat: This is a mental model for *React*. Once you start adding a whole
|
|
bunch of tooling on top of React, you're on your own.]
|
|
|
|
A React application has a collection of one or more *states*. A complex
|
|
application may have orthoganal states: the user's identity, tracking the page
|
|
they're currently looking at, one or more forms the customer has interact with,
|
|
and so on. React listens to these states and, where you have specified that a
|
|
state change has a consequential visual change on the page, React automatically
|
|
updates the page.
|
|
|
|
All input from React should be channeled up to the aggregate collection of
|
|
states, and your React app should be written such that it correctly responds to
|
|
that change. It's a singular loop with no internal contradictions.
|
|
|
|
React creates a tree internally that describes the visual result of the current
|
|
state. When you update the state, that tree is rebuilt, compared to the
|
|
previous version, and only those parts of the HTML that are directly affected
|
|
are updated.
|
|
|
|
Never forget: React's output is a tree. React's behavior is an event loop. React
|
|
is a recursive engine operating on a recursive data structure, it manipulates
|
|
another recursive data structure (the browser's Document Object Model, or DOM),
|
|
and success depends upon *your* data being able to fit into that exact same
|
|
model.
|
|
|
|
## JSX
|
|
|
|
``` typescript
|
|
import React from "react";
|
|
import ReactDOM from "react-dom";
|
|
|
|
const Hello = <h1>Hello, World!</h1>;
|
|
const root = ReactDOM.createRoot(document.getElementById('root'));
|
|
root.render(<Hello />);
|
|
```
|
|
|
|
This is the smallest possible React program that shows React and JSX. JSX is an
|
|
XML-like addition that you write directly into your Javascript. All JSX
|
|
functions begin with a capital letter, to distinguish from plain old HTML, which
|
|
is always begun with a lower case letter. That `Hello` is a function; under the
|
|
covers, the JSX parser turns it into a bit of code that generates the HTML and,
|
|
if specified, hooks up event handlers.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Git is project and folder-centered, and to start using git go to the root folder
|
|
of a project you want to place under source control and initialize it:
|
|
|
|
```bash
|
|
$ mkdir a-new-project
|
|
$ touch README.md
|
|
$ git init
|
|
```
|
|
|
|
This creates a new folder, `.git`, where Git will store your commit history and
|
|
some configuration details. Git will usually not create a repository without
|
|
_something_ to store in it, but see the [`git start` alias](#config) below.
|
|
|
|
## Putting files into git
|
|
|
|
To put files under source control, you must add them. To update the entire
|
|
folder, switch to the root of the project and add _all_ of it:
|
|
|
|
```bash
|
|
$ git add .
|
|
$ git commit
|
|
```
|
|
|
|
An editor will pop-up, asking you what this commit is about. It's generally
|
|
polite, especially if you're working in a team, to explain your commit in some
|
|
detail-- and to generally keep the commit small, in order to ensure that you
|
|
don't have to explain too much!
|
|
|
|
If your commit message could be a single line, you can add it directly from the
|
|
command line:
|
|
|
|
```bash
|
|
$ git add .
|
|
$ git commit -m "Updated the widget to widgetize."
|
|
```
|
|
|
|
... and you can even combine both commands, but be careful: this command will
|
|
not add any files that are new. It will only commit existing files that have
|
|
been modified, and will delete any files that you have deleted, from the
|
|
repository. (Deleted files still exist in the history and can always be
|
|
recovered.)
|
|
|
|
```bash
|
|
$ git commit -am "Updated the widget to widgetize."
|
|
```
|
|
|
|
## Git Configuration {#config}
|
|
|
|
You can have a global Git configuration file, `$HOME/\.gitconfig`, in which you
|
|
keep your personal information and command aliases, which is one of three ways
|
|
you can add your own commands to Git.
|
|
|
|
```bash
|
|
[user]
|
|
name = Elf M. Sternberg
|
|
email = someguy@example.com
|
|
|
|
[alias]
|
|
unstage = reset -q HEAD --
|
|
nevermind = !git reset --hard HEAD && git clean -d -f
|
|
wip = for-each-ref --sort='authordate:iso8601' --format='%(color:green)%(authordate:relative)%09%(color:white)%(refname:short)' refs/heads
|
|
stem = "!f() { git checkout -b $1 develop; }; f"
|
|
start = !git init && git commit --allow-empty -m \"Initial commit\"
|
|
```
|
|
|
|
## Git Aliases {#aliases}
|
|
|
|
Aliases are commands that you can run *in git* as if they were part of the git
|
|
toolset, but their functionality is defined by you. The five aliases shown
|
|
above are my "must haves." They represent the way I work.
|
|
|
|
- `unstage` is something I do a lot. Maybe it's my ADHD, but I often add
|
|
something to the git staging area, then realize that the work was incomplete
|
|
and have to go back. This command does that, and I hated memorizing it.
|
|
- `nevermind` is for when your work has gone off the rails; your stab at solving
|
|
the problem has taken you places you didn't want to be. This command resets
|
|
you to exactly where you were before you started hacking.
|
|
- `wip` stands for "works in progress"; it shows you a list of branches
|
|
currently live in your local project, in the order from oldest to newest, with
|
|
a text that tells you your last commit was "yesterday" or "3 months ago".
|
|
- `stem` creates a new branch off the develop branch (you can change that to
|
|
main or canon or whatever). This is the most common workflow I have at home,
|
|
and this command allows me to get to it quickly. The syntax tells git to use
|
|
the bash to populate the new branch name, as the default alias format can
|
|
only take arguments at the end, and the new branch name must be injected
|
|
before the source branch.
|
|
- `start` creates a git repository out of a completely empty folder. This might
|
|
seem odd, but it's actually a very useful way of introducing a new project and
|
|
ensuring git is ready to go.
|
|
|
|
## Git Extensions
|
|
|
|
Just like aliases, you can add whole unique commands to git, as long as the
|
|
extension name doesn't conflict with one of git's internal commands. The
|
|
syntax for doing so is to create a script (in any language!) and name it
|
|
`git-your-extension-name`, and you call it by invoking git and giving it the
|
|
extension name.
|
|
|
|
For example, if you write documentation and you want to know how many words
|
|
you've written since your last commit, you can create a Bash script named
|
|
`git-wc` (word count):
|
|
|
|
``` bash
|
|
#!/bin/bash
|
|
REM=`git diff --word-diff=porcelain -U $* | grep '^-' | sed 's/^-//' | wc -w`
|
|
ADD=`git diff --word-diff=porcelain -U $* | grep '^+' | sed 's/^+//' | wc -w`
|
|
DIF=`expr $ADD - $REM`
|
|
echo "Word count: $DIF"
|
|
```
|
|
|
|
## Add vs Commit
|
|
|
|
You may have noticed that there's a two-step to committing your work; you `add`
|
|
it, then `commit` it. `add`ing it puts it into the `staging area`. The primary
|
|
goal of this design is to allow you to commit only parts of your project, rather
|
|
than committing everything at once. By creating an index of what-to-commit, and
|
|
then allowing you to write your commit message afterward, you have more control
|
|
over the development process.
|
|
|
|
If you're completely reassured of your skillz as a _leet koder dood_, you could
|
|
always create an alias that stages, commits, and pushes to your remote
|
|
repository all at once. I don't recommend that.
|
|
|
|
|
|
|
|
|
|
|