Skip to main content

React.js

React (Facebook)​

  • JavaScript UI library
    • not a full fledged framework because React has no router
      • however, there is a package called react-router-dom
  • Maintained by Facebook
  • alternatives to React:
    • Angular (2016, Google, full fledged framework)
      • complete rewrite of AngularJS
      • TypeScript based
    • Vue.js (2014, Evan You, gaining popularity, easy to learn)

JSX (Facebook)​

AKA JavaScript Syntax Extension, (JavaScript XML)

  • looks like HTML
  • React components are typically written using JSX (but can also be written in pure JavaScript)
    • JSX provides a way to structure component rendering
  • JSX is a syntax extension of JavaScript
    • JSX was created by Facebook
    • similarly, XHP is a syntax extension for PHP
      • XHP was also created by Facebook

Using JavaScript inside of JSX​

  • wrap the code in curly braces

Tutorials​

digitalocean.com​

Setup for the digitalocean.com Tutorial​

Setup for the digitalocean.com Tutorial
npx create-react-app my-app-name

# Delete the line `import logo from './logo.svg';`. Then replace everything in
# the return statement to return a set of empty tags: <></>.
nvim src/App.js
rm src/logo.svg

# Each component will have its own directory in 'components/' to store the
# component file along with the styles, images, and tests.
mkdir src/components
mkdir src/components/App

# Move all of the App files into that directory.
mv src/App.* src/components/App/

# change line to: `import App from './components/App/App';`
nvim src/index.js

Fundamentals​

Elements​

Components​

  • React components
  • "Conceptually, components are like JavaScript functions."
  • "They accept arbitrary inputs (called "props") and return React elements describing what should appear on the screen."

Lists and Keys​

From legacy.reactjs.org:

Creating a list:

Transforming arrays into lists of React elements:

How to transform arrays in JavaScript
// create an array
const numbers = [1, 2, 3, 4, 5];
// iterate over this array
const doubled = numbers.map((number) => number * 2);

// print the result
console.log(doubled);

Usually you would render lists inside a React component.

Refactor the previous example into a React component that accepts an array of numbers and outputs a html unordered list of React elements:

A React component that accepts an array of numbers and outputs a html unordered list of React elements
function NumberList(props) {
const numbers = props.numbers;
const listItems = numbers.map((number) =>
<li>{number}</li>
);
return (
<ul>{listItems}</ul>
);
}

const numbers = [1, 2, 3, 4, 5];
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<NumberList numbers={numbers} />);
List elements need keys!

This will throw a warning in the Firefox Console (ctrl shift k) (it may be necessary to reload the page ctrl shift r before this is shown).

http://localhost:3000
Warning: Each child in a list should have a unique "key" prop.

Check the render method of `NumberList`. See https://reactjs.org/link/warning-keys for more information.
li
NumberList@http://localhost:3001/static/js/bundle.js:24:19

Fix this warning by adding a key:

Add a key
function NumberList(props) {
const numbers = props.numbers;
const listItems = numbers.map((number) =>
<li key={number.toString()}>
{number}
</li>
);
return (
<ul>{listItems}</ul>
);
}
  • "Keys should be given to the elements inside the array to give the elements a stable identity"
How to pick a key (from legacy.reactjs.org)

"When you don’t have stable IDs for rendered items, you may use the item index as a key as a last resort:"

const todoItems = todos.map((todo, index) =>
// Only do this if items have no stable IDs
<li key={index}>
{todo.text}
</li>
);

"We don't recommend using indexes for keys if the order of items may change. This can negatively impact performance and may cause issues with component state."

State Management​

  • state management: In React development, keeping track of how your application data changes over time is called "state management".
    • common state management methods:
      • class-based state management
      • Hooks
      • Redux (third-party library)
    • React may optimize code by calling actions asynchronously
      • make sure that your function has access to the most up-to-date state

setState(nextState, callback?)​

From: react.dev: setState

Parameters​

  • nextState: Either an object or a function.
    • If you pass an object as nextState, it will be shallowly merged into this.state.
    • If you pass a function as nextState, it will be treated as an updater function. It must be pure, should take the pending state and props as arguments, and should return the object to be shallowly merged into this.state. React will put your updater function in a queue and re-render your component. During the next render, React will calculate the next state by applying all of the queued updaters to the previous state.
  • optional callback: If specified, React will call the callback you’ve provided after the update is committed.

Usage​

From: react.dev: setState

  • "Call setState to update the state of your React component."
  • "setState enqueues changes to the component state. It tells React that this component and its children need to re-render with the new state."
  • "This is the main way you’ll update the user interface in response to interactions."
  • "You can also pass a function to setState. It lets you update state based on the previous state: example"

3 things you should know about setState()​

From: legacy.reactjs.org: with examples

1. Do not modify state directly​

For example, this will not re-render a component:

// Wrong
this.state.comment = 'Hello';

Instead, use setState():

// Correct
this.setState({comment: 'Hello'});
  • "The only place where you can assign this.state is the constructor."
    • if you assign it somewhere else, the component will not re-render
  • use spread for copying arrays
2. State updates may be asynchronous​
  • React may batch multiple setState() calls into a single update for performance.
  • Because this.props and this.state may be updated asynchronously, you should not rely on their values for calculating the next state.

For example, this code may fail to update the counter [phth: counter is like the total price in the digitalocean tutorial]:

// Wrong
this.setState({
counter: this.state.counter + this.props.increment,
});

To fix it, use a second form of setState() that accepts a function rather than an object. That function will receive the previous state as the first argument, and the props at the time the update is applied as the second argument:

// Correct
this.setState((state, props) => ({
counter: state.counter + props.increment
}));

We used an arrow function above, but it also works with regular functions:

// Correct
this.setState(function(state, props) {
return {
counter: state.counter + props.increment
};
});
3. State updates are merged​

When you call setState(), React merges the object you provide into the current state.

For example, your state may contain several independent variables [here: posts and comments]:

constructor(props) {
super(props);
this.state = {
posts: [],
comments: []
};
}

Then you can update them independently with separate setState() calls:

componentDidMount() {
fetchPosts().then(response => {
this.setState({
// this "setState" call updates only "this.state.posts", but not "this.state.comments"!
posts: response.posts
});
});

fetchComments().then(response => {
this.setState({
// this "setState" call updates only "this.state.comments", but not "this.state.posts"!
comments: response.comments
});
});
}

The merging is shallow, so this.setState({comments}) leaves this.state.posts intact, but completely replaces this.state.comments.

Hooks​

  • since React 16
  • Hooks are functions
  • Hooks are triggered
    • by other actions
    • when a component's props change
  • Hooks are used to
    • create data
    • to trigger further changes
  • Since this method of state management doesn't require you to use classes, developers can use Hooks to write shorter, more readable code that is easy to share and maintain.
  • One of the main differences between Hooks and class-based state management is that there is no single object that holds all of the state. Instead, you can break up state into multiple pieces that you can update independently.

Built-in Hooks​

useState​

  • a function
  • takes the initial state as an argument and returns an array with two items
  • syntax: const [variable, setFunction] = useState(defaultValue);
    • event handler function: the event handler function (i.e. the function in onClick={function}) must have the same scope as the setFunction, therefore the event handler function must be defined inside the component function
      • if you define the arrow function inside of a prop (i.e. substitute function in onClick={function} with the definition of function), React will
        1. create a new function in every re-render
        2. which triggers a prop change
        3. which causes the component to re-render
      • if you define the arrow function outside of a prop, you can use the useCallback Hook which will memoize (cache) the function
        • this gives better performance than defining the function inside of a prop
      • as a rule, the higher a component is likely to be in a tree, the greater the need for memoization.

useContext​

useReducer​

  • specially designed to update the state based on the current state, in a manner similar to the .reduce array method
  • The useReducer Hook is similar to useState, but when you initialize the Hook, you pass in a function the Hook will run when you change the state along with the initial data
  • The function - referred to as the reducer - takes two arguments:
    • the state
    • The other argument is what you will supply when you call the update function.
  • A common pattern in reducer functions is to pass an object as the second argument that contains
    • the name of the action and
    • the data for the action.
    • Inside the reducer, you can then update the total based on the action.

Redux​

  • a method of state management
  • a third-party library
  • also follows the React Hook naming convention, i.e. Redux Hooks also start with the prefix use...
    • e.g. useSelector, useStore

Best Practice in State Management​

  • It is best to only add information to state that you expect to change
    • This way, the information in state will be easier to keep track of as your application scales.
  • minimize the different pieces of state by only saving related data in one place
    • In other words, try to avoid double references to the same data

Performance​

Lazy Loading​

From Wiki:

  • also known as asynchronous loading
  • a design pattern commonly used in computer programming and mostly in web design and development to defer initialization of an object until the point at which it is needed.
  • It can contribute to efficiency in the program's operation if properly and appropriately used.
  • This makes it ideal in use cases where network content is accessed and initialization times are to be kept at a minimum, such as in the case of web pages.
    • For example, deferring loading of images on a web page until they are needed can make the initial display of the web page faster.
  • The opposite of lazy loading is eager loading.

create-react-app (cra)​

  • CLI tool to quickly spin up a React app
  • loosing popularity because of Next.js
  • official doc
npx create-react-app my-app
# or:
npx create-react-app my-app --template [template-name]
# start the app:
npm start

Components of a cra Project​

root component: src/App.js is the root component that is injected into the page. All components will start from here.

Rename a cra Project​

  • must rename multiple things:
    • First, rename the project folder, eg. mv -iv my-app/ my-new-app-name/
    • Then, in package.json and package-lock.json replace all occurrences of the old name my-app/ with my-new-app-name/.

cra Templates​

react-scripts​

  • for example
    • npm run start (or npm start) runs react-scripts start
    • npm run test (or npm test) runs react-scripts test
    • etc.

From: stackoverflow

  • react-scripts is a set of scripts from the create-react-app starter pack. create-react-app helps you kick off projects without configuring, so you do not have to setup your project by yourself.
  • npm start is a shortcut for npm run start.
  • npm run is used to run scripts that you define in the scripts object of your package.json
  • if there is no start key in the scripts object, it will default to node server.js
  • Sometimes you want to do more than the react scripts gives you, in this case you can do react-scripts eject. This will transform your project from a "managed" state into a not managed state, where you have full control over dependencies, build scripts and other configurations.
package.json
{
...
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
...
}

Docusaurus​

Creates a documentation page in React that is easy to maintain.

E.g. the create-react-app doc was built using Docusaurus (see source code on github).

Installation​

For more details see docusaurus doc.

nvm install lts/hydrogen --latest-npm
nvm alias default lts/hydrogen
nvm use lts/hydrogen

Generate a new Docusaurus Website​

npx create-docusaurus@latest my-website classic

Or create a blank template:

npm init docusaurus@latest

Local Development​

$ cd my-website/
$ npm start

This command starts a local development server and opens up a browser window. Most changes are reflected live without having to restart the server.

Local Build​

Always build it locally before you push it to Gitlab.

npm run build
npm run serve