<Hello />

React Basics

 

  • Components

  • JSX

  • Props

  • Rendering

  • Events

  • State

  • Context

  • useEffect

React Advanced

 

  • Routing

  • TypeScript

  • State Management

  • Testing

  • Forms

  • ...

Setup

 

npx create-next-app@latest

 

Other Options, see: https://react.dev/learn/start-a-new-react-project

Components

Practice 👨‍💻🧑‍💻

Import / Export

Default vs Named Exports

Default vs Named Exports

Galaxus mini 👨‍💻🧑‍💻

Export the Card Component

 

Export the Card component and place it a few times into the App Component. Try it as Default Import / Export and also as Named Import / Export.

 

https://codesandbox.io/s/galaxus-mini-components-gb0ltp

 

Solution 💡 https://codesandbox.io/s/galaxus-mini-components-solution-82kz7i

JSX

1. Return a single root element

To return multiple elements from a component, wrap them with a single parent tag.

If you don’t want to add an extra <div> to your markup, you can write <> and </> instead:

 

2. Close all the tags

JSX requires tags to be explicitly closed: self-closing tags like <img> must become <img />

 

3. camelCase most of the things!

Pro-tip: Use a JSX Converter

Converting all these attributes in existing markup can be tedious!

 

https://transform.tools/html-to-jsx

 

Practice 👨‍💻🧑‍💻

Convert some HTML to JSX

https://codesandbox.io/s/html-convert-dlgvpq

 

JavaScript in JSX with Curly Braces

 

When you want to pass a string attribute to JSX, you put it in single or double quotes.

If you want to dynamically specify the src or alt text, you could use a value from JavaScript by replacing " and " with { and }:

Any JavaScript expression will work between curly braces, including function calls like formatDate():

Using “double curlies”: CSS and other objects in JSX

In addition to strings, numbers, and other JavaScript expressions, you can even pass objects in JSX.

 

 

Practice 👨‍💻🧑‍💻

Galaxus mini 👨‍💻🧑‍💻

Extract some Data

 

In the <Card> Component, extract the Image URL, Title, Price and Availability into Variables or an Object. Then use them in the JSX markup using Curly Brackets.

 

https://codesandbox.io/s/galaxus-mini-components-solution-82kz7i

 

Solution 💡 https://codesandbox.io/s/galaxus-mini-jsx-solution-jyjv0k

 

 

Passing Props to a Component

React components use props to communicate with each other.

 

Every parent component can pass some information to its child components by giving them props.

 

 

Step 1: Pass props to the child component

Step 2: Read props inside the child component

Specifying a default value for a prop

If you want to give a prop a default value to fall back on when no value is specified, you can do it with destructuring by putting = and the default value right after the parameter:

 

Forwarding props with the JSX spread syntax

Sometimes, passing props gets very repetitive.

 

In those cases you can use the Spread Operator to forward all your props. 

Optional Practice 👨‍💻🧑‍💻

Extract a component

This Gallery component contains some very similar markup for two profiles. Extract a Profile component out of it to reduce the duplication. You’ll need to choose what props to pass to it.

 

https://codesandbox.io/s/props-extract-wnwrwh

 

Hint: Start by extracting the markup for one of the scientists. Then find the pieces that don’t match it in the second example, and make them configurable by props

How props change over time

A component may receive different props over time.

Props are not always static!

 

In the following example, the time prop changes every second, and the color prop changes when you select another color. And whenever props change, the React Component re-renders

Galaxus mini 👨‍💻🧑‍💻

Pass Data down as Props

 

Move the Card Data (Title, Price etc.) into the App Component and pass it down to the Cards as Props. In the Card component, define default values for each prop.

Bonus: add a new Prop isFavorite to show the Heart in Pink color (text-pink-400) for certain products.

 

https://codesandbox.io/s/galaxus-mini-jsx-solution-jyjv0k

 

Solution 💡 https://codesandbox.io/s/galaxus-mini-props-solution-zu6wmh

 

 

Rendering

Conditional (ternary) operator

Instead of this:

 

You can write this:

Logical AND operator (&&)

Rendering Lists

 

Arrow Functions

 

React Fragment

 

Practice 👨‍💻🧑‍💻

Splitting a list in two

 

This example shows a list of all people. Change it to show two separate lists one after another: Chemists and Everyone Else. You can determine whether a person is a chemist by checking if person.profession === 'chemist'.

 

https://codesandbox.io/s/rendering-persons-xfyzw3

 

Solution 💡 https://codesandbox.io/s/rendering-persons-solution-7ymvgw

Galaxus mini 👨‍💻🧑‍💻

Render Cards as a List

 

Create an Array with different Card Data (Title, Price etc.) for each Card. Loop over the Array to render the Cards. You can find images for your products in the public/images folder.

Bonus: add a new Prop showSizes to hide the available Sizes on the Card if the product does not have a size (i.e. Tequila)

 

https://codesandbox.io/s/galaxus-mini-props-solution-zu6wmh
 

Solution 💡 https://codesandbox.io/s/galaxus-mini-rendering-solution-jhqp0g

 

 

Events

React lets you add event handlers to your JSX. Event handlers are your own functions that will be triggered in response to interactions like clicking, focusing and so on.

Alternative Syntax

Instead of passing a function, you can write the Event Handler inline:

 

Or using an Arrow Function:

Practice 👨‍💻🧑‍💻

Fix an Event handler

 

Clicking the button is supposed to switch the page background between white and black. However, nothing happens when you click it. Fix the problem. (Don’t worry about the logic inside handleClick — that part is fine.)

 

https://codesandbox.io/s/events-toggle-the-lights-gky5xy


Solution 💡 https://codesandbox.io/s/events-toggle-the-lights-solution-wpf9qj

Galaxus mini 👨‍💻🧑‍💻

Add Event Listener

 

In the Card Component, add onClick Events for the Add to Cart button and the Favorite Button. The Events should just log to the Console (console.log) what was clicked i.e. Add to Cart: Dom Perignon.

Bonus: add onChange Event Listener to the Sizes Selection and save which size was selected.

 

https://codesandbox.io/s/galaxus-mini-rendering-solution-jhqp0g

 

Solution 💡 https://codesandbox.io/s/galaxus-mini-events-solution-7736rz

 

 

State

Components often need to change what’s on the screen as a result of an interaction.

 

For example, typing into the form should update the input field. Clicking “next” on an image carousel should change which image is displayed etc.

When a regular variable isn’t enough

1. Local variables don’t persist between renders. When React renders this component a second time, it renders it from scratch—it doesn’t consider any changes to the local variables.

 

2. Changes to local variables won’t trigger renders. React doesn’t realize it needs to render the component again with the new data.

 

Example https://codesandbox.io/s/state-local-variable-xgkjgz

Adding a state variable

Meet your first Hook

In React, useState, as well as any other function starting with ”use,” is called a Hook.

A simple Example

Practice 👨‍💻🧑‍💻

Complete the gallery

 

When you press “Next” on the last sculpture, the code crashes. Fix the logic to prevent the crash. You may do this by adding extra logic to event handler or by disabling the button when the action is not possible.

After fixing the crash, add a “Previous” button that shows the previous sculpture. It shouldn’t crash on the first sculpture.

 

https://codesandbox.io/s/state-gallery-jc8m4m


Solution 💡 https://codesandbox.io/s/state-gallery-solution-l6wmmf

Galaxus mini 👨‍💻🧑‍💻

Use State in the Card Component

 

Use one useState Hook to save for each Card if it is in the Cart and if it is a Favorite. Bonus: save which Size is selected.

Use that State to toggle the buttons i.e. show "✓ Added to Cart" and change the color of the Favorite Button.

 

https://codesandbox.io/s/galaxus-mini-events-solution-7736rz

 

Solution 💡 https://codesandbox.io/p/sandbox/galaxus-mini-state-solution-jpljqp

 

 

React batches state updates

Updating the same state variable multiple times 

useState Updater Function

Overall, using an updater function with setState provides flexibility, ensures the most up-to-date state, and allows for complex state updates or performance optimizations.

 

When the next State depends on the previous State it's best to use an updater function.

 

Counter Example https://codesandbox.io/s/counter-updater-function-dpkxdh

 

More Info: https://react.dev/reference/react/useState#setstate-caveats

Updating Objects in State

 

State can hold any kind of JavaScript value, including objects. But you should not change objects that you hold in the React state directly.

Instead, when you want to update an object, you need to create a new one (or make a copy of an existing one), and then set the state to use that copy.

 

Example Mutating the State directly does not work

https://codesandbox.io/s/state-mutating-objects-j3hs62

 

Copying objects with the spread syntax

We need to use the setState Function to Update the state. And we need to copy the existing data into it.

 

Object Spread Syntax:

Updating a nested object

To update a nested Object, we need to copy each "Level".

Changing the city prop:

Write concise update logic with Immer

Practice 👨‍💻🧑‍💻

Replace the Updating Logic

 

Use Immer JS to simplify the state Updating Logic.

https://codesandbox.io/s/state-immer-kkcz78

 

 

Solution 💡 https://codesandbox.io/s/state-immer-solution-2m3zw7

Updating Arrays in State

 

 

Updating an Array

Add something:

Sharing State Between Components

 

Sometimes, you want the state of two components to always change together.

 

To do it, remove state from both of them, move it to their closest common parent, and then pass it down to them via props.

Lifting state up by example

Notice how pressing one panel’s button does not affect the other panel—they are independent.

 

 

But now let’s say you want to change it so that only one panel is expanded at any given time.

Step 1: Remove state from the child components

Step 2: Add state to the common parent

Galaxus mini 👨‍💻🧑‍💻

Lift State Up

 

Lift the state handleAddToCart up from the Card Component into the App Component.

 

Bonus: show on the Cart Icon how many Products are currently in the Bag.

 

https://codesandbox.io/p/sandbox/galaxus-mini-state-solution-jj4jg3

 

Solution 💡 https://codesandbox.io/p/sandbox/galaxus-mini-state-up-solution-53vrq9

 

 

Context

Context lets the parent component make some information available to any component in the tree below it—no matter how deep—without passing it explicitly through props.

Step 1: Create the context

The only argument to createContext is the default value.

Step 2: Use the context

Import the useContext Hook from React and your context.

Read the value from the context you just imported.

Step 3: Provide the context

Even though we’re using the context, we have not provided it yet.  React just uses the default value we specified in the previous step.

Practice 👨‍💻🧑‍💻

Replace prop drilling with context

 

Toggling the checkbox changes the imageSize prop passed to each <PlaceImage>. The checkbox state is held in the top-level App component, but each <PlaceImage> needs to be aware of it. 

Currently, App passes imageSize to List, which passes it to each Place, which passes it to the PlaceImage. Remove the imageSize prop, and instead pass it from the App component directly to PlaceImage. You can declare context in Context.js.

 

https://codesandbox.io/s/context-prop-drilling-2fl3yn

Solution 💡 https://codesandbox.io/s/context-prop-drilling-solution-x62vmf

Use Cases for Context

Context is very tempting to use! However, this also means it’s too easy to overuse it. Just because you need to pass some props several levels deep doesn’t mean you should put that information into context.

 

Good Use Cases for context

  • Theming: If your app lets the user change its appearance (e.g. dark mode).
  • Current account: When components might need to know the currently logged in user.
  • Routing: Most routing solutions use context internally to hold the current route. This is how every link “knows” whether it’s active or not.
  • Managing state: As your app grows, you might end up with a lot of state closer to the top of your app. Many distant components below may want to change it. It is common to use a reducer together with context to manage complex state.

Galaxus mini 👨‍💻🧑‍💻

Use Context for the Bag Count

 

Don't pass the count via Props to the MiniCart Component. Instead, use Context to provide it.

 

Bonus: Use Context to Provide a Dark Theme to every Component. The Theme is currently hardcoded to light in most Components.

 

https://codesandbox.io/p/sandbox/galaxus-mini-state-up-solution-dng35k

 

Solution 💡 https://codesandbox.io/s/galaxus-mini-context-solution-0tq066

 

 

UseEffect

The Effect Hook lets you perform side effects in function components.

 

A side effect can be data fetching, setting up a subscription or manually changing the DOM.

 

In other words: Effects let you run some code after rendering so that you can synchronize your component with some system outside of React.

Possible Use Cases

  • Data Fetching: Load some data when the component is rendered for the first time.

 

  • Focus an Inputfield: You want to set the Focus into an Inputfield when it renders.

 

  • Using a jQuery Plugin: Initalize a jQuery Plugin (i.e. Datepicker) when the React Component mounts and destroy it when the Component unmounts.
     
  • ...

Basic Example

Dependencies

Per default, the side effect inside useEffect runs on every Render.

 

We can provide a Dependency Array to run the effect only when one of the dependencies changes.

Dependencies

1. Side Effect Runs After Every Render

 

 

 

 

3. Side Effect Runs After State Value Changes

 

2. Side Effect Runs Only Once After Initial Render

 

 

 

 

4. Side Effect Runs After Props Value Change

 

 

Cleanup Function

Certain effects need cleanup when the React Component unmounts.

 

Whatever we return from an useEffect Hook will be run when the Component unmounts.

Cleanup Function

Data Fetching

In simple application we can use the useEffect Hook for Data Fetching.

Custom Hook

Often times, a custom hook is created with useEffect for Data Loading.

Not an Effect

1. You don’t need Effects to transform data for rendering. Just do it in the render method.

 

2. You don’t need Effects to handle Events.

For example, let’s say you want to send an /api/buy POST request and show a notification when the user buys a product. Just do it in the Event Handler.

Galaxus mini 👨‍💻🧑‍💻

Fetch the Products and the Cart

 

Fetch data by using two useEffect Hooks. Use getProducts() and getCartItems() to load data from the API.

 

https://codesandbox.io/s/galaxus-mini-use-effect-d2w0bw 

→ neue Sandbox mit Loading Spinner, bitte diese verwenden.

 

Solution 💡 https://codesandbox.io/s/galaxus-mini-use-effect-solution-br9yxq

 

 

Routing

We use React Router for our application.

https://reactrouter.com

Link

A relative <Link to> value (that does not begin with /) resolves relative to the parent route. It may contain .. to link to routes further up the hierarchy.

Nested Routes

Dashboard will render in the <Outlet>:

  • <DashboardMessages> when the URL is "/messages"
  • <DashboardTasks> when the URL is "/tasks"
  • null when the URL is"/"

Galaxus mini 👨‍💻🧑‍💻

Route to the Cart Page


Use React Router to create a new Cart Page and navigate to it.

  • When clicking on the MiniCart, navigate to the Cart Page.
  • When clicking on the Galaxus Logo, navigate back to the Homepage.
  • When clicking on "Zurück zur Produktliste", navigate back to the Homepage.

https://codesandbox.io/p/sandbox/galaxus-mini-router-4v5kqc

→ neue Sandbox mit Router, bitte diese verwenden.


Solution 💡 https://codesandbox.io/s/galaxus-mini-router-solution-cp5w7d



TypeScript

In this chapter we will cover some common Use Cases for TypeScript with React.

 

A comprehensive overview can be found in the following Cheatsheet:

 

https://github.com/typescript-cheatsheets/react

Components

Props and State

You can define your Props using a Type or using an Interface. Using a Type seems to be a more common these days for for typing React Props and State.

Components

Extending Props

Sometimes you want to take component props declared for one component and extend them to use them on another component. But you might want to modify one or two.

Components

Some Examples

Here are just some common examples for typing Props.

Forms & Events

React uses its own event system. That’s why you can’t use typical MouseEvent or similar on your elements. You need to use the specific React version

Type the Event

Restric Event to an Element

Forms & Events

One of the most common cases is correctly typing the onChange event used on an input field in a form.

useState

TypeScript can infer the values of the useState hook:

When you need to initialize a hook with a null-ish value, you can make use of a generic and pass a union to correctly type your hook:

useEffect

You don’t need to provide any extra typings. TypeScript will check that the method signature of the function you provide is correct and makes sure you return a function for the cleanup.

Context

You can type the Context by using a Generic in the createContext Function.

Galaxus mini 👨‍💻🧑‍💻

Add Typings to the Application

Add Typings for cartProducts State in the App Component.

Add Typings for CardProps and CardState in the Card Component.

 

https://codesandbox.io/s/galaxus-mini-typescript-ud8775

→ neue Sandbox mit TSX, bitte diese verwenden.

 

Solution 💡 https://codesandbox.io/s/galaxus-mini-typescript-solution-37fsmu

 

 

State Management

Global State Management helps with Prop Drilling, accessing Data without duplicating it, Data Fetching...

 

 

Client & Server State

Global State Management can be divided in Client State and Server State.

 

Until now we just used setState and Context for Client State. And we used useEffect for Server State.

Client State

Server State

Client State

This kind of state lives only on the Client and is not persited on the Server. It is synchronous, not async.

 

Use Cases:

  • Global Layout States (is the Sidebar Open..)
  • Theming  (dark, light..)
  • ...

Client State

Out of the Box

For simple State that lives inside of a component we can use setState. We can lift state up and provide it to some Child Components. With Context we can provide it to all components.

 

Most applications do not have complex Client state. With Context (and possibly useReducer) we can build our own a simple State Management.

Client State

useReducer

tbd

Client State

Libraries

Redux is the de-facto standard. It can also handle Server State and has awesome DevTools. People complain about too much boilerplate to accomplish simple things. Redux Toolkit solves a lot of those issues.

 

MobX provides simple, scalable state management by using Observables.

 

Zustand is a newer Library that is currently hyped.

Client State

Redux

tbd

Server State

Managing Server State is a lot harder than Client State. 

 

Things we need: Fetching, Caching, Invalidating and Updating Server Data. And Loading States.

 

Bonus Features: Polling, Optimistic Updates, Pagination, Prefetching server data.

Server State

Out of the Box

In a useEffect Hook we can fetch data from a Server and use useState to save and re-render the Component.

 

...but it has a few downsides and lacks a lot of useful features.

Server State

Why not just useEffect?

Fetching directly in Effects makes it easy to create “network waterfalls”. You render the parent component, it fetches some data, renders the child components, and then they start fetching their data.

 

Fetching directly in Effects usually means you don’t preload or cache data. For example, if the component unmounts and then mounts again, it would have to fetch the data again.

 

Fetching all data of your application in the <App> component loads unnecessary data and does not scale well.

Server State

Libraries

React Query and SWR a popular Libraries for managing Server State.

 

When using GraphQL, Apollo is a popular and comprehensive Library.

 

Libraries for Client & Server

Many Libraries tried to solve Client and Server State in one Library i.e. Redux Toolkit Query.

 

Modern State Management Libraries focus on solving just one of those, because the challenges are completely different.

 

Let's have a look at a modern Server State Library, React Query.

React Query

React Query in 100 Seconds

https://www.youtube.com/watch?v=novnyCaa7To

 

Example

https://codesandbox.io/s/react-query-intro-dq5jcj

  • Cached Data
  • Loading States
  • Background Refetching

React Query

Queries

A query is a declarative dependency on an asynchronous source of data that is tied to a unique key.

 

The unique key you provide is used internally for refetching, caching, and sharing your queries throughout your application.

React Query

Queries

The query result contains all of the information about the query that is needed for templating and any other usage of the data.

 

React Query

Stale Queries

Per default, every cache Query is considered as stale data.

 

Stale queries are refetched automatically in the background when:

  • New instances of the query mount
  • The window is refocused
  • The network is reconnected.

React Query

Named Queries aka Custom Hooks

Each query can be refactored to be it's own custom hook. This design is the suggested way to use React Query, as it makes it much easier to manage query keys and shared query logic.

React Query

Invalidating Queries

 

Waiting for queries to become stale before they are fetched again doesn't always work, especially when you know for a fact that a query's data is out of date because of something the user has done.

React Query

Mutations

Mutations are used to create/update/delete data. For this purpose, React Query exports a useMutation hook.

React Query

Optimistic Updates

Galaxus mini 👨‍💻🧑‍💻

Use React Query for Server State

 

  • In MiniCart.tsx refactor the useQuery to use a custom Query useCartProducts.ts

 

https://codesandbox.io/s/galaxus-mini-state-management-uykx2s

Solution 💡 https://codesandbox.io/s/galaxus-mini-state-management-solution-ttp2id

 

 

Testing

Test Runner & Tools

 

  • Jest is a JavaScript test runner that lets you access the DOM via jsdom. Alternatives: Mocha, ava.
     
  • React Testing Library is a set of helpers that let you test React components without relying on their implementation details. Alternative: Enzyme.
     
  • Cypress for End-to-End Testing. Alternatives: Playwright, Puppeteer.

Jest

Snapshot Testing

 

Snapshot tests are a very useful tool whenever you want to make sure your UI does not change unexpectedly.

 

React Testing Library

Unit Testing

 

The React Testing Library is a light-weight solution for testing React components. It provides utility functions in a way that encourages better testing practices.

 

The goal is not to test implementation details but real user interactions.

 

Testing Library runs on top of Jest and is a replacement for Enzyme.

React Testing Library

Finding DOM Nodes

 

The utilities facilitate querying the DOM in the same way the user would i.e. finding elements by their label text, finding links from their text etc. like a user would.

 

 

HTML

Testing Library Query

React Testing Library

Finding DOM Nodes

It also exposes a recommended way to find elements by a data-testid as an "escape hatch" for elements where the text content and label do not make sense or is not practical.

HTML

Testing Library Query

React Testing Library

Debugging​

 

For convenience screen also exposes a debug method in addition to the queries. It supports debugging the document, a single element, or an array of elements.

React Testing Library

User Actions​

 

React Testing Library

Examples

 

https://codesandbox.io/s/testing-library-examples-gk2htq

 

Siehe Files im src/__tests__ folder.

 

Galaxus mini 👨‍💻🧑‍💻

Write some Tests

Download the Sandbox as ZIP and add a Snapshot Test.

 

Write a new Test to check if a Product was marked as Favorite.

 

https://codesandbox.io/s/galaxus-mini-testing-library-46ey1n

 

Solution 💡 https://codesandbox.io/s/galaxus-mini-testing-library-solution-ji8ckv

 

 

Forms

Controlled vs. uncontrolled Forms

 

HTML form elements work a bit differently from other DOM elements in React, because form elements naturally keep some internal state.

 

There are two approaches: controlled and uncontrolled Forms.

 

https://codesandbox.io/s/forms-uncontrolled-controlled-1l0nfe

Forms

Controlled vs. uncontrolled Forms

 

With Controlled forms, we have access to all values all the time. This can be useful for i.e. validation checks. 

 

The recommendation is to use controlled Forms.

Forms

Library

 

Formik is a great Library for Forms.

https://formik.org

 

 

https://codesandbox.io/s/formik-h62tyj

React JS

By Dominic Modalek