Rendering strategy router integration
Rendering strategies need to integrate with the router so apps can choose the rendering strategy on a per-route level. This enables different rendering strategies without rewriting the whole app. For example, a landing page might benefit from static generation (SSG) while a content feed might perform best with server-side rendering.
Static site generation (SSG) characteristics
Static site generation (SSG) generates static HTML files for an app at build time. SSG can improve performance but is more complex to set up and maintain than server-side rendering. Vite provides an SSG guide at https://vite.dev/guide/ssr.html#pre-rendering-ssg
Single-page app (SPA) characteristics
Single-page apps load a single HTML page and dynamically update the page as the user interacts with the app. SPAs are easier to get started with but can have slower initial load times. SPAs are the default architecture for most build tools.
Server-side rendering (SSR) characteristics
Server-side rendering (SSR) renders a page on the server and sends the fully rendered page to the client. SSR can improve performance but is more complex to set up and maintain than a single-page app. With streaming SSR, the setup and maintenance can be very complex. Vite provides an SSR guide at https://vite.dev/guide/ssr
React Server Components (RSC) characteristics
React Server Components (RSC) lets you mix build-time, server-only, and interactive components in a single React tree. RSC can improve performance but currently requires deep expertise to set up and maintain. Parcel provides RSC examples at https://github.com/parcel-bundler/rsc-examples
Conditionally assigning JSX to a variable
Use an if statement with a variable to conditionally assign JSX content. Declare a variable with let, provide a default value, then use an if statement to reassign it if a condition is true. Embed the variable in the returned JSX using curly braces. This approach is more verbose but offers more flexibility than ternary operators or && shortcuts.
Control flow in React components
In React, control flow like conditions is handled by JavaScript. You can use JavaScript's if statements, return statements, and other control flow mechanisms to conditionally render different JSX.
JSX elements as lightweight descriptions
JSX elements are not 'instances' because they do not hold internal state and are not real DOM nodes. They are lightweight descriptions, like blueprints. Two different conditional branches that return identical JSX elements are completely equivalent.
Extract child components to simplify complex conditionals
If a component gets messy with too much nested conditional markup, consider extracting child components to clean things up. In React, markup is part of your code, so you can use variables, functions, and components to tidy up complex expressions.
Pitfall: don't put numbers on left side of && operator
Do not use a number on the left side of the && operator in conditional rendering. JavaScript converts the left side to a boolean, but if the left side is 0, the whole expression evaluates to 0, and React will render the 0 instead of nothing. To fix this, make the left side a boolean: messageCount > 0 && <p>New messages</p> instead of messageCount && <p>New messages</p>.
Ternary operator with nested JSX
You can nest complex JSX elements inside a ternary operator. Wrap each branch in parentheses when the JSX spans multiple lines. Example: {isPacked ? (<del>{name + ' ✅'}</del>) : (name)}. This allows conditional rendering of more complex markup while avoiding duplication.
Returning null to render nothing
A component can conditionally return null to render nothing at all. When a condition is true, return null; otherwise, return JSX. React treats null as a 'hole' in the JSX tree and does not render anything in its place.
Ternary operator for conditional rendering
Use the JavaScript ternary operator (? :) to conditionally include JSX. The syntax is: {condition ? valueIfTrue : valueIfFalse}. For example: {isPacked ? name + ' ✅' : name} means 'if isPacked is true, render name + checkmark, otherwise render name'. This avoids duplicating JSX markup.
Logical AND operator for conditional rendering
Use the JavaScript && operator to render JSX only when a condition is true, or render nothing otherwise. The syntax is: {condition && <JSX />}. For example: {isPacked && '✅'} means 'if isPacked is true, render the checkmark, otherwise render nothing'. React considers false, null, and undefined as 'holes' in the JSX tree and does not render anything.
if/else statements for conditional JSX rendering
You can return different JSX conditionally using if statements inside a component. If the condition is true, return one JSX tree; otherwise, return a different JSX tree. For example: if (isPacked) { return <li>{name} ✅</li>; } return <li>{name}</li>;
Self-closing tags in JSX must end with />
In JSX, HTML elements that are self-closing in HTML must be written with a closing slash. For example, <img /> instead of <img>.
JSX elements must have a single root element
You cannot return multiple JSX elements from a component without wrapping them in a parent element. Use a fragment (<></>) as an empty wrapper when you need to return multiple elements without adding an extra DOM node.
Avoid modifying preexisting variables in components
Do not change variables that existed before the component was called. Instead, pass the data you need as props. This keeps your components pure and predictable.
Pure functions have no side effects and consistent output
A pure function minds its own business (does not change any objects or variables that existed before it was called) and returns the same output given the same inputs. By strictly writing your components as pure functions, you can avoid baffling bugs and unpredictable behavior as your codebase grows.
Use className instead of class in JSX
In JSX, the HTML attribute class must be written as className. This is one of the differences between JSX and HTML that makes JSX stricter.
Use curly braces to access JavaScript in JSX
Curly braces in JSX allow you to 'open a window' to JavaScript, letting you add JavaScript logic or reference dynamic properties inside markup. You can use curly braces to embed variables, expressions, and function calls within JSX.
Export and import components into separate files
You can declare many components in one file, but large files can get difficult to navigate. To solve this, you can export a component into its own file and then import that component from another file.
JSX is stricter than HTML
Each React component is a JavaScript function that may contain markup using JSX, a syntax extension that looks like HTML but is stricter and can display dynamic information. If you paste existing HTML markup into a React component, it won't always work.
Props allow parent-to-child communication
React components use props to communicate with each other. Every parent component can pass some information to its child components by giving them props. Props might remind you of HTML attributes, but you can pass any JavaScript value through them, including objects, arrays, functions, and even JSX.
React render tree shows component relationships
A React render tree is a representation of the parent and child relationship between components. Components near the top of the tree, near the root component, are considered top-level components. Components with no child components are leaf components. This categorization is useful for understanding data flow and rendering performance.
Module dependency tree shows JavaScript module relationships
A module dependency tree models the relationships between JavaScript modules based on which files import which other files. A dependency tree is often used by build tools to bundle all the relevant JavaScript code for the client to download and render. Understanding the module dependency tree is helpful to debug bundle size issues.
Conditionally render with if, &&, and ternary operators
In React, you can conditionally render JSX using JavaScript syntax like if statements, the && operator, and the ternary ? : operator. For example, you can use the && operator to conditionally render a checkmark: {isPacked && '✅'}.
Use className for CSS classes in React
In React, you specify a CSS class with `className`. It works the same way as the HTML `class` attribute. You write CSS rules in a separate CSS file and reference them using `className`.
Embed JavaScript in JSX with curly braces
In JSX, you can use curly braces to escape back into JavaScript. Single curly braces let you embed variables and complex expressions directly in JSX markup. For attributes, you use curly braces instead of quotes: `src={user.imageUrl}` reads the JavaScript variable, while `className="avatar"` passes a string.
JSX syntax and requirements
JSX is a markup syntax used in React. JSX is stricter than HTML: you must close tags like `<br />`, and a component cannot return multiple JSX tags. You must wrap multiple tags into a shared parent, like `<div>...</div>` or an empty `<>...</>` wrapper.
Inline styles in React use object syntax
Inline styles in React use double curly braces: `style={{}}`. The outer braces escape into JavaScript, and the inner braces create a regular JavaScript object. You can use this when your styles depend on JavaScript variables.
Conditional rendering with if statements
React has no special syntax for conditions. You use the same techniques as regular JavaScript. You can use an `if` statement to conditionally include JSX by storing the result in a variable before the return statement.
Conditional rendering with logical AND operator
When you don't need the `else` branch, you can use the logical `&&` operator: `{condition && <Component />}`. This renders the component only if the condition is true.
React components are JavaScript functions
React components are JavaScript functions that return markup. A component is a piece of the UI (user interface) that has its own logic and appearance.
Conditional rendering with ternary operator
You can use the conditional `?` operator inside JSX for more compact conditional rendering. The syntax is `{condition ? <ComponentIfTrue /> : <ComponentIfFalse />}`.
Reference object properties in JSX
You can move JavaScript values into an object and reference them in JSX using dot notation. For example, define `const person = { name: 'John', theme: { backgroundColor: 'black' } }` and then use `<div style={person.theme}><h1>{person.name}</h1></div>` to access those properties.
Cannot render plain objects as JSX children
Attempting to render a JavaScript object directly as text content in JSX throws an error: "Objects are not valid as a React child". For example, `<h1>{person}'s Todos</h1>` will fail if `person` is an object. You must access a specific property instead, such as `<h1>{person.name}'s Todos</h1>` to render a string value.
Combine strings using expressions in JSX attributes
String concatenation can be performed inside JSX curly braces to dynamically build attribute values. For example, `src={baseUrl + person.imageId + person.imageSize + '.jpg'}` combines multiple variables and string literals into a complete URL within a single expression.
Inline style properties use camelCase in JSX
When using inline styles in JSX, style properties must be written in camelCase, not kebab-case as in HTML. For example, HTML `style="background-color: black"` becomes `style={{ backgroundColor: 'black' }}` in JSX. This applies to all CSS properties used as inline styles in React components.
Use curly braces to insert JavaScript variables into JSX
To dynamically specify attribute values or embed JavaScript variables in JSX, replace quotes with curly braces. For example, change `src="url"` to `src={urlVariable}` to read the value of a JavaScript variable. Curly braces open a window to JavaScript within JSX markup.
Pass strings to JSX attributes with quotes
String attributes in JSX are passed by putting them in single or double quotes. For example, `className="avatar"` and `src="https://example.com/image.jpg"` pass strings directly as attribute values.
Valid locations for curly braces in JSX
Curly braces can be used in exactly two ways inside JSX: (1) As text directly inside a JSX tag, such as `<h1>{name}'s To Do List</h1>`, and (2) As attributes immediately following the `=` sign, such as `src={avatar}`. Curly braces cannot wrap tag names like `<{tag}>` or be quoted like `src="{avatar}"`, which would pass the literal string "{avatar}" instead of the variable value.
JavaScript expressions work inside JSX curly braces
Any JavaScript expression can be used between curly braces in JSX, including variable references, function calls, and arithmetic operations. For example, `<h1>{formatDate(today)}</h1>` calls the `formatDate` function and displays its return value.
Double curly braces for objects in JSX
When passing a JavaScript object in JSX, you must wrap the object in double curly braces because objects use curly braces in their syntax. For example, `style={{ backgroundColor: 'black', color: 'pink' }}` passes an object to the style attribute. The outer curly braces open the JavaScript expression, and the inner curly braces define the object literal.
Do not mutate props, state, or context
You should not mutate any of the inputs that your components use for rendering. That includes props, state, and context. To update the screen, use state setters instead of mutating preexisting objects.
Component rendering order is not guaranteed
Rendering can happen at any time, so components should not depend on each other's rendering sequence. You should not expect your components to be rendered in any particular order. Each component should only think for itself and not attempt to coordinate with or depend upon others during rendering.
Benefits of component purity
Writing pure components unlocks several benefits: components can run in different environments (for example, on the server) since they return the same result for the same inputs; performance can be improved by skipping rendering of components whose inputs have not changed since pure functions always return the same results and are safe to cache; if data changes during rendering a deep component tree, React can restart rendering without wasting time finishing the outdated render since purity makes it safe to stop calculating at any time.
Pure component example: Recipe
Example of a pure component: function Recipe({ drinkers }) { return ( <ol><li>Boil {drinkers} cups of water.</li><li>Add {drinkers} spoons of tea and {0.5 * drinkers} spoons of spice.</li><li>Add {0.5 * drinkers} cups of milk to boil and sugar to taste.</li></ol> ); } When you pass drinkers={2} to Recipe, it will return JSX containing 2 cups of water. Always. If you pass drinkers={4}, it will return JSX containing 4 cups of water. Always.
Enable Strict Mode in React
To opt into Strict Mode, wrap your root component into <React.StrictMode>. Some frameworks do this by default.
Fix impurity by using props instead of mutations
To fix an impure component that mutates external state, pass the needed value as a prop instead. Example fix: function Cup({ guest }) { return <h2>Tea cup for guest #{guest}</h2>; } Then call it with explicit prop values: <Cup guest={1} /> <Cup guest={2} /> <Cup guest={3} /> Now the component is pure because the JSX it returns only depends on the guest prop.
Side effects must not occur during render phase
React's rendering process must always be pure. Components should only return their JSX, and not change any objects or variables that existed before rendering. Changing preexisting variables or objects during rendering makes components impure.
Local mutation is acceptable during rendering
It is completely fine to change variables and objects that you have just created while rendering. For example, creating an array and pushing items into it during the same render is acceptable because the array and variables were created within the component's scope, not before it.
Pure function definition
A pure function has two characteristics: it minds its own business (does not change any objects or variables that existed before it was called), and same inputs produce the same output (given the same inputs, a pure function should always return the same result).
React assumes components are pure functions
React is designed around the concept of pure functions. React assumes that every component you write is a pure function, which means React components must always return the same JSX given the same inputs.
Strict Mode detects impure components
React's Strict Mode calls each component's function twice during development to help find components that break purity rules. By calling component functions twice, Strict Mode exposes impure behavior. Pure functions only calculate, so calling them twice will not change anything. Strict Mode has no effect in production and will not slow down the app for users.
Impure component example: mutating external variable
Example of an impure component: let guest = 0; function Cup() { guest = guest + 1; return <h2>Tea cup for guest #{guest}</h2>; } This component reads and writes a guest variable declared outside of it, making it impure. Calling this component multiple times produces different JSX, and other components reading guest will produce different JSX depending on when they were rendered.
Local mutation example: building array during render
Example of acceptable local mutation: function TeaGathering() { const cups = []; for (let i = 1; i <= 12; i++) { cups.push(<Cup key={i} guest={i} />); } return cups; } This is fine because the cups array and the variable are created during the same render inside TeaGathering. No code outside of TeaGathering will ever know this mutation happened. This is called local mutation.
Props are JSX attributes used for component communication
Props are the information passed to a JSX tag to enable parent components to communicate with child components. You can pass any JavaScript value through props, including objects, arrays, and functions. Props work similarly to HTML attributes for built-in elements.
How to pass props to a component
To pass props to a component, add them to the JSX tag like HTML attributes. For example: <Avatar person={{name: 'Lin Lanying', imageId: '1bX5QH6'}} size={100} />. Props can be any value: objects, arrays, numbers, strings, or functions.
How to read props inside a component using destructuring
Inside a component function, read props by destructuring their names directly in the function parameters: function Avatar({ person, size }) { }. This allows you to use person and size as variables inside the component. Alternatively, you can access them as properties of a props object: function Avatar(props) { let person = props.person; }.