<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0">
    <channel>
        <title><![CDATA[Rami Chabchoub's Blog]]></title>
        <description><![CDATA[Developer & Creator sharing unique tips and articles about web development]]></description>
        <link>https://www.ramicode.com</link>
        <image>
            <url>https://www.ramicode.com/og?title=Rami%20Chabchoub</url>
            <title>Rami Chabchoub&apos;s Blog</title>
            <link>https://www.ramicode.com</link>
        </image>
        <generator>Next.js RSS Feed Generator</generator>
        <lastBuildDate>Wed, 18 Jun 2025 01:54:59 GMT</lastBuildDate>
        <atom:link href="https://www.ramicode.com/feed.xml" rel="self" type="application/rss+xml"/>
        <pubDate>Wed, 18 Jun 2025 01:54:59 GMT</pubDate>
        <copyright><![CDATA[© 2025 Rami Chabchoub]]></copyright>
        <language><![CDATA[en]]></language>
        <ttl>60</ttl>
        <item>
            <title><![CDATA[JavaScript Primer]]></title>
            <description><![CDATA[A comprehensive guide to JavaScript, the programming language of the web.]]></description>
            <link>https://www.ramicode.com/en/articles/javascript-primer</link>
            <guid isPermaLink="false">javascript-primer</guid>
            <dc:creator><![CDATA[Rami Chabchoub]]></dc:creator>
            <pubDate>Sun, 08 Jun 2025 00:00:00 GMT</pubDate>
            <content:encoded><![CDATA[&lt;h1&gt;01 String Interpolation&lt;/h1&gt;
&lt;p&gt;In earlier versions of JavaScript, if we wanted to dynamically create strings, we needed to use the addition operator (+):&lt;/p&gt;

```javascript showLineNumbers
const userName = &apos;Mai&apos;;
const dynamicString = &apos;hello &apos; + userName + &apos;!&apos;;
```


&lt;p&gt;This works alright, but it feels pretty clunky at times, and can lead to bugs (eg. forgetting the space in &lt;code&gt;Hello &lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;Modern JavaScript allows us to embed variables and other expressions right inside strings:&lt;/p&gt;

```javascript showLineNumbers
const dynamicString = `hello ${userName}!`;
```


&lt;p&gt;In order to use string interpolation, we need to use backticks (`).&lt;/p&gt;
&lt;p&gt;Strings created with backticks are known as &amp;quot;template strings&amp;quot;. For the most part, they function just like any other string, but they have this one super-power: they can embed dynamic segments.&lt;/p&gt;
&lt;p&gt;We create a dynamic segment within our string by writing &lt;code&gt;${}&lt;/code&gt;. Anything placed between the squiggly brackets will be evaluated as a JavaScript expression.&lt;/p&gt;
&lt;p&gt;This means that we can do fancy things like this:&lt;/p&gt;

```javascript showLineNumbers
const age = 7;
console.log(`Next year, you&apos;ll be ${age + 1} years old.`);
```


&lt;p&gt;This creates the string &amp;quot;Next year, you&amp;#39;ll be 8 years old.&amp;quot;.&lt;/p&gt;
&lt;h1&gt;02 Arrow Functions&lt;/h1&gt;
&lt;p&gt;Historically, functions in JavaScript have been written using the &lt;code&gt;function&lt;/code&gt; keyword:&lt;/p&gt;

```javascript showLineNumbers
function exclaim(string) {
  return string + &apos;!&apos;;
}
```


&lt;p&gt;In 2015, the language received an alternative syntax for creating functions: arrow functions. They look like this:&lt;/p&gt;

```javascript showLineNumbers
const exclaim = string =&gt; string + &apos;!&apos;;
```


&lt;p&gt;Arrow functions are inspired by lambda functions from other functional programming languages. Their main benefit is that they&amp;#39;re much shorter and cleaner. Reducing &amp;quot;function clutter&amp;quot; may seem like an insignificant benefit, but it can really help improve readability when working with anonymous functions. For example:&lt;/p&gt;

```javascript showLineNumbers
const arr = [&apos;hey&apos;, &apos;ho&apos;, &apos;let\&apos;s go&apos;];

&lt;p&gt;// This:
arr
  .map(function(string) {
    return string + &amp;#39;!&amp;#39;
  })
  .join(&amp;#39; &amp;#39;);&lt;/p&gt;
&lt;p&gt;// …Becomes this:
arr
  .map(string =&amp;gt; string + &amp;#39;!&amp;#39;)
  .join(&amp;#39; &amp;#39;);&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;/CodeBlock&amp;gt;

## Rules of arrow functions

Arrow functions might seem straightforward at first glance, but there are a few &amp;quot;gotchas&amp;quot; to be aware of. It&amp;#39;s super common for folks to get tripped up by some of these rules.

## Short-form vs. long-form

There are two types of arrow functions: short-form and long-form.

Here&amp;#39;s the short-form:

&amp;lt;CodeBlock title=&amp;quot;short-form-arrow&amp;quot;&amp;gt;
```javascript showLineNumbers
const add1 = n =&amp;gt; n + 1;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;And here&amp;#39;s the long-form:&lt;/p&gt;

```javascript showLineNumbers
const add1 = n =&gt; {
  return n + 1;
};
```


&lt;p&gt;We opt into the long form by adding curly braces (&lt;code&gt;{ }&lt;/code&gt;) around the function body.&lt;/p&gt;
&lt;p&gt;The fundamental difference between the two forms is this:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The short-form function&amp;#39;s body must be a single expression. That expression will be automatically returned.&lt;/li&gt;
&lt;li&gt;The long-form function&amp;#39;s body can contain a number of statements. We need to manually specify the return.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;With the short-form, our function body consists of a single expression, and that expression will be returned. This is sometimes called an &amp;quot;implicit&amp;quot; return, because there&amp;#39;s no &lt;code&gt;return&lt;/code&gt; keyword.&lt;/p&gt;
&lt;p&gt;When we add the squiggly brackets (&lt;code&gt;{ }&lt;/code&gt;), we create a block of statements. We can put as many statements as we want in there. We need to specify what should be returned using a &lt;code&gt;return&lt;/code&gt; statement.&lt;/p&gt;
&lt;p&gt;Interestingly, if we try to add the return keyword to the short-form syntax, we&amp;#39;ll get a syntax error:&lt;/p&gt;

```javascript showLineNumbers
const add1 = n =&gt; return n + 1;
// Uncaught SyntaxError: Unexpected token &apos;return&apos;
```


&lt;p&gt;Why is this an error? Well, &lt;code&gt;return n + 1&lt;/code&gt; is a statement, not an expression. The short form requires an expression. We&amp;#39;re not allowed to put a statement there.&lt;/p&gt;

Sometimes, we&apos;ll see arrow functions written like this:

&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;const shout = sentence =&amp;gt; (
  sentence.toUpperCase()
);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;What does it mean when we use parentheses (&lt;code&gt;( )&lt;/code&gt;) instead of curly braces (&lt;code&gt;{ }&lt;/code&gt;)?&lt;/p&gt;
&lt;p&gt;Parentheses can be added to help us with formatting. By adding parens, we&amp;#39;re able to push the returned expression to a new line. And so, we&amp;#39;re still using the short-form &amp;quot;implicit&amp;quot; return structure, but we&amp;#39;re restructuring it to make it more readable.&lt;/p&gt;
&lt;p&gt;To put it another way, these two functions are identical:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;// On multiple lines, with parens:
const shoutWithParens = sentence =&amp;gt; (
  sentence.toUpperCase()
);

// Or, in a single line without parens:
const shoutWithoutParens = sentence =&amp;gt; sentence.toUpperCase();
&lt;/code&gt;&lt;/pre&gt;


&lt;h2&gt;Optional parameter parentheses&lt;/h2&gt;
&lt;p&gt;If an arrow function takes a single parameter, the parentheses are optional:&lt;/p&gt;

```javascript showLineNumbers
// This is valid:
const logUser = user =&gt; {
  console.log(user);
}

&lt;p&gt;// This is also valid:
const logUser = (user) =&amp;gt; {
  console.log(user);
}&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;/CodeBlock&amp;gt;

The parentheses are mandatory if we have more than 1 parameter:

&amp;lt;CodeBlock title=&amp;quot;multiple-parameters&amp;quot;&amp;gt;
```javascript showLineNumbers
const updateUser = (user, properties, isAdmin) =&amp;gt; {
  if (!isAdmin) {
    throw new Error(&amp;#39;Not authorized&amp;#39;)
  }

  user.setProperties(properties);
}
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;The parentheses are also mandatory if we have no parameters:&lt;/p&gt;

```javascript showLineNumbers
const sayHello = () =&gt; console.log(&apos;Hello!&apos;)
```


&lt;h2&gt;Implicitly returning objects&lt;/h2&gt;
&lt;p&gt;Let&amp;#39;s suppose we have a function which returns an object:&lt;/p&gt;

```javascript showLineNumbers
function makeObject() {
  return {
    hi: 5,
  };
}
```


&lt;p&gt;Something sorta funny happens when we try and convert it to a short-form arrow function:&lt;/p&gt;

```javascript showLineNumbers
const makeObject = () =&gt; { hi: 5 };
```


&lt;p&gt;There are two ways we could interpret this code:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;A short-form arrow function that returns an object, &lt;code&gt;{ hi: 5 }&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;A long-form arrow function with a single statement, &lt;code&gt;hi: 5&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The problem is that curly braces (&lt;code&gt;{}&lt;/code&gt;) serve two purposes in JavaScript: they&amp;#39;re used for object notation, but they&amp;#39;re also used to create blocks, like in &lt;code&gt;if&lt;/code&gt; statements.&lt;/p&gt;
&lt;p&gt;When curly braces follow an arrow (&lt;code&gt;=&amp;gt;&lt;/code&gt;), the JS engine assumes we&amp;#39;re creating a new block, and so we&amp;#39;ll get a syntax error, since &lt;code&gt;hi: 5&lt;/code&gt; is not a valid JS statement.&lt;/p&gt;
&lt;p&gt;If we want to implicitly return an object, we need to wrap it in parentheses:&lt;/p&gt;

```javascript showLineNumbers
const makeObject = () =&gt; ({ hi: 5 });
```


&lt;p&gt;In JavaScript, parentheses can be added around any expression, to change its evaluation order. In this case, we don&amp;#39;t care about evaluation order, we just need to make it clear that we&amp;#39;re trying to pass an expression.&lt;/p&gt;
&lt;p&gt;Similarly, it&amp;#39;s common to wrap the short-form expression in parentheses when it&amp;#39;s too long to fit on a single line:&lt;/p&gt;

```javascript showLineNumbers
const matchedItem = items.find(item =&gt; (
  item.color === &apos;red&apos; &amp;&amp; item.size === &apos;large&apos;
));
```


&lt;p&gt;We can wrap any expression in parentheses, but we can&amp;#39;t wrap a block in parentheses. And so, when we wrap the &lt;code&gt;{}&lt;/code&gt; characters in parens, the engine can figure out that we&amp;#39;re trying to create an object, not a block.&lt;/p&gt;
&lt;h1&gt;03 Object Destructuring&lt;/h1&gt;
&lt;p&gt;Object destructuring offers a sleek way to extract some variables from an object.&lt;/p&gt;
&lt;p&gt;Here&amp;#39;s a quick example:&lt;/p&gt;

```javascript showLineNumbers
const user = {
  name: &apos;François Bouchard&apos;,
  city: &apos;Saint-Louis-du-Ha! Ha!&apos;,
  province: &apos;Québec&apos;,
  country: &apos;Canada&apos;,
  postalCode: &apos;A1B 2C3&apos;,
};

&lt;p&gt;const { name, country } = user;&lt;/p&gt;
&lt;p&gt;console.log(name); // &amp;#39;François Bouchard&amp;#39;
console.log(country); // &amp;#39;Canada&amp;#39;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;/CodeBlock&amp;gt;

This is effectively the same thing as doing this:

&amp;lt;CodeBlock title=&amp;quot;traditional-property-access&amp;quot;&amp;gt;
```javascript showLineNumbers
const name = user.name;
const country = user.country;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;We can pluck out as many or as few values as we want.&lt;/p&gt;
&lt;h2&gt;Renaming extracted values&lt;/h2&gt;
&lt;p&gt;Consider this situation:&lt;/p&gt;

```javascript showLineNumbers
const name = &apos;Hello!&apos;;

&lt;p&gt;const user = { name: &amp;#39;Marie-Hélene Pelletier&amp;#39; };&lt;/p&gt;
&lt;p&gt;const { name } = user;
// Uncaught SyntaxError:
// Identifier &amp;#39;name&amp;#39; has already been declared&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;/CodeBlock&amp;gt;

We tried to destructure the `name` property into its own variable, but we run into an issue: there&amp;#39;s already a variable called `name`!

In these cases, we can rename the value as we unpack it:

&amp;lt;CodeBlock title=&amp;quot;renaming-destructured-values&amp;quot;&amp;gt;
```javascript showLineNumbers
const name = &amp;#39;Hello!&amp;#39;;

const user = { name: &amp;#39;Marie-Hélene Pelletier&amp;#39; };

const { name: userName } = user;

console.log(name); // &amp;#39;Hello!&amp;#39;
console.log(userName); // &amp;#39;Marie-Hélene Pelletier&amp;#39;
&lt;/code&gt;&lt;/pre&gt;


&lt;h2&gt;Default values&lt;/h2&gt;
&lt;p&gt;Here&amp;#39;s a question: what happens if we try to destructure a key from an object which isn&amp;#39;t defined?&lt;/p&gt;

```javascript showLineNumbers
const user = { name: &apos;Marie-Hélene Pelletier&apos; };

&lt;p&gt;const { status } = user;&lt;/p&gt;
&lt;p&gt;console.log(status); // ???&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;/CodeBlock&amp;gt;

Well, `user.status` isn&amp;#39;t defined, and so `status` will be set to `undefined`.

If we want, we can set a default value using the assignment operator:

&amp;lt;CodeBlock title=&amp;quot;default-values&amp;quot;&amp;gt;
```javascript showLineNumbers
const { status = &amp;#39;idle&amp;#39; } = user;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;if the user object has a &lt;code&gt;status&lt;/code&gt; property, that value will be plucked out and assigned to the new &lt;code&gt;status&lt;/code&gt; constant. Otherwise, &lt;code&gt;status&lt;/code&gt; will be assigned to the string &amp;quot;idle&amp;quot;.&lt;/p&gt;
&lt;p&gt;In order words, it&amp;#39;s a modern version of this:&lt;/p&gt;

```javascript showLineNumbers
const status = typeof user.status === &apos;undefined&apos;
  ? &apos;idle&apos;
  : user.status;
```


&lt;h2&gt;Destructuring function parameters&lt;/h2&gt;
&lt;p&gt;Let&amp;#39;s suppose we have a function which takes an object as its first parameter:&lt;/p&gt;

```javascript showLineNumbers
function validateUser(user) {
  if (typeof user.name !== &apos;string&apos;) {
    return false;
  }

&lt;p&gt;  if (user.password.length &amp;lt; 12) {
    return false;
  }&lt;/p&gt;
&lt;p&gt;  return true;
}&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;/CodeBlock&amp;gt;

If we wanted, we could destructure these values at the top of the function:

&amp;lt;CodeBlock title=&amp;quot;destructuring-inside-function&amp;quot;&amp;gt;
```javascript showLineNumbers
function validateUser(user) {
  const { name, password } = user;

  if (typeof name !== &amp;#39;string&amp;#39;) {
    return false;
  }

  if (password.length &amp;lt; 12) {
    return false;
  }

  return true;
}
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;Using parameter destructuring, we can do this destructuring right in the function parameters:&lt;/p&gt;

```javascript showLineNumbers
function validateUser({ name, password }) {
  if (typeof name !== &apos;string&apos;) {
    return false;
  }

&lt;p&gt;  if (password.length &amp;lt; 12) {
    return false;
  }&lt;/p&gt;
&lt;p&gt;  return true;
}&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;/CodeBlock&amp;gt;

All 3 of these code snippets are equivalent, but many developers enjoy using function parameter destructuring. It&amp;#39;s especially popular in React to destructure the props in our components.

## Named arguments

Some languages have &amp;quot;named arguments&amp;quot;, where the developer can choose to label the arguments they&amp;#39;re passing into a function.

JavaScript doesn&amp;#39;t have this feature, and as a result, it can be difficult to understand what role different arguments play.

For example, suppose you&amp;#39;re working on a codebase, and you stumble upon this code:

&amp;lt;CodeBlock title=&amp;quot;mysterious-arguments&amp;quot;&amp;gt;
```javascript showLineNumbers
trackSession(user.id, 5, null);
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;Why does this function receive a &lt;code&gt;5&lt;/code&gt; and a &lt;code&gt;null&lt;/code&gt;? It&amp;#39;s totally mysterious. We&amp;#39;d need to hunt down the file where this function is defined to understand what these values are.&lt;/p&gt;
&lt;p&gt;Suppose, though, that &lt;code&gt;trackSession&lt;/code&gt; took an object as its only argument.&lt;/p&gt;
&lt;p&gt;Then it would look like this:&lt;/p&gt;

```javascript showLineNumbers
trackSession({
  userId: user.id,
  version: 5,
  additionalMetadata: null,
});
```


&lt;p&gt;By supplying an object, we effectively have to label each value! This works quite a lot like &amp;quot;named arguments&amp;quot; in other languages!&lt;/p&gt;
&lt;p&gt;When I write a function, I&amp;#39;ll often use parameter destructuring specifically so that I can pass an object in, rather than a bunch of individual arguments. That way, it&amp;#39;s easier to understand what the provided data is.&lt;/p&gt;
&lt;h2&gt;Default parameter values&lt;/h2&gt;
&lt;p&gt;Like with typical object destructuring, we can supply default values to be used for parameters.&lt;/p&gt;
&lt;p&gt;Here&amp;#39;s a quick example:&lt;/p&gt;

```javascript showLineNumbers
function sendApiRequest({ method = &apos;GET&apos;, numOfRetries }) {
  // Stuff
}
```


&lt;p&gt;When I call this function, I can supply my own value for &lt;code&gt;method&lt;/code&gt;:&lt;/p&gt;

```javascript showLineNumbers
sendApiRequest({ method: &apos;PUT&apos;, numOfRetries: 4 });
```


&lt;p&gt;…Or, if I want it to be equal to GET, I can omit it entirely:&lt;/p&gt;

```javascript showLineNumbers
sendApiRequest({ numOfRetries: 4 });
```



Let&apos;s suppose we add default values for both of the properties in our function:

&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;function sendApiRequest({ method = &amp;#39;GET&amp;#39;, numOfRetries = 5 }) {
  // Stuff
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We then call this function without specifying an argument, since we want to use all of the default values:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;sendApiRequest();
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Unfortunately, we get an error:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Uncaught TypeError: Cannot read properties of undefined (reading &amp;#39;method&amp;#39;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Here&amp;#39;s the problem: we&amp;#39;re destructuring the &lt;code&gt;method&lt;/code&gt; and &lt;code&gt;numOfRetries&lt;/code&gt; properties from an object, but when we call the &lt;code&gt;sendApiRequest&lt;/code&gt; function, we&amp;#39;re not providing an object.&lt;/p&gt;
&lt;p&gt;Here&amp;#39;s another example of the same issue, which might make it clearer:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;function sendApiRequest(properties) {
  // `properties` is undefined, and so we&amp;#39;ll get the same
  // error when we try and extract values from it:
  const {
    method = &amp;#39;GET&amp;#39;,
    numOfRetries = 5
  } = properties;
}

sendApiRequest();
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;To solve this problem, we can set a default value for the first parameter, the object we&amp;#39;re destructuring from:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;function sendApiRequest(
  { method = &amp;#39;GET&amp;#39;, numOfRetries = 5 } = {}
) {
  // Stuff
}

sendApiRequest(); // ✅ No problem!
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;When we call &lt;code&gt;sendApiRequest&lt;/code&gt; without passing in any arguments, the first parameter gets initialized to an empty object. Then, the &lt;code&gt;method&lt;/code&gt; and &lt;code&gt;numOfRetries&lt;/code&gt; properties are initialized using their default values, since they weren&amp;#39;t defined in that empty object.&lt;/p&gt;
&lt;p&gt;This stuff gets pretty complex. You certainly don&amp;#39;t need to take advantage of all of this modern syntax. I just wanted to let you know that this is an issue you might run into.
&lt;/p&gt;
&lt;h1&gt;04 Property Value Shorthand&lt;/h1&gt;
&lt;p&gt;Objects in modern JavaScript have a nifty little trick up their sleeve. It&amp;#39;s a small thing, but if you&amp;#39;re not aware of it, it can cause a lot of confusion.&lt;/p&gt;
&lt;p&gt;Suppose we have the following code:&lt;/p&gt;

```javascript showLineNumbers
const name = &apos;Ahmed&apos;;
const age = 26;

&lt;p&gt;const user = {
  name: name,
  age: age,
};&lt;/p&gt;
&lt;p&gt;console.log(user);
// { name: &amp;#39;Ahmed&amp;#39;, age: 26 }&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;/CodeBlock&amp;gt;

We&amp;#39;re creating a user object with two properties, `name` and `age`. We&amp;#39;re assigning those properties to variables of the same name.

It does feel a bit redundant, though, doesn&amp;#39;t it? We&amp;#39;re assigning `name` to `name`, and assigning `age` to `age`.

Modern JavaScript gives us a convenient shorthand we can use in this situation:

&amp;lt;CodeBlock title=&amp;quot;property-value-shorthand&amp;quot;&amp;gt;
```javascript showLineNumbers
const name = &amp;#39;Ahmed&amp;#39;;
const age = 26;

const user = {
  name,
  age,
};

console.log(user);
// { name: &amp;#39;Ahmed&amp;#39;, age: 26 }
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;This is known as the property value shorthand. When creating an object, we can omit the values if they share the same name as the property.&lt;/p&gt;
&lt;p&gt;The end result is the same, but it&amp;#39;s a bit more terse.&lt;/p&gt;
&lt;h1&gt;05 Array Destructuring&lt;/h1&gt;
&lt;p&gt;Suppose we have some data that lives in an array, and we want to pluck it out and assign it to a variable.&lt;/p&gt;
&lt;p&gt;Traditionally, this has been done by accessing an item by index, and assigning it a value with a typical assignment statement:&lt;/p&gt;

```javascript showLineNumbers
const fruits = [&apos;apple&apos;, &apos;banana&apos;, &apos;cantaloupe&apos;];
const firstFruit = fruits[0];
const secondFruit = fruits[1];
```


&lt;p&gt;Destructuring assignment offers us a nicer way to accomplish this task:&lt;/p&gt;

```javascript showLineNumbers
const fruits = [&apos;apple&apos;, &apos;banana&apos;, &apos;cantaloupe&apos;];
const [firstFruit, secondFruit] = fruits;
```


&lt;p&gt;The first time you see it, those array brackets before the &lt;code&gt;=&lt;/code&gt; look pretty wild.&lt;/p&gt;
&lt;p&gt;Here&amp;#39;s how I think about it: when the &lt;code&gt;[ ]&lt;/code&gt; characters are used after the assignment operator (&lt;code&gt;=&lt;/code&gt;), they&amp;#39;re used to package items into an array. When they&amp;#39;re used before, they do the opposite, and they unpack items from an array:&lt;/p&gt;

```javascript showLineNumbers
// Packing 3 values into an array:
const array = [1, 2, 3];

&lt;p&gt;// Unpacking 3 values from an array:
const [first, second, third] = array;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;/CodeBlock&amp;gt;

Ultimately, this isn&amp;#39;t really a game-changer, but it&amp;#39;s a neat little party trick that can tidy things up a bit.

&amp;lt;Update title=&amp;quot;Disclaimer&amp;quot;&amp;gt;
## Skipping items

What if we only wanted to grab the second item, and not the first? Can we use destructuring assignment in that case?

In fact, we can:

```javascript
const fruits = [&amp;#39;apple&amp;#39;, &amp;#39;banana&amp;#39;, &amp;#39;cantaloupe&amp;#39;];
const [, secondFruit] = fruits;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We&amp;#39;ve removed &lt;code&gt;firstFruit&lt;/code&gt;, but kept the comma. Essentially, we&amp;#39;ve left a gap where the first variable used to be. If you&amp;#39;re familiar with sheet music, you can think of it like a rest.&lt;/p&gt;
&lt;p&gt;Technically, we can leave many gaps, picking and choosing the items we want:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;const fruits = [
  &amp;#39;apple&amp;#39;,
  &amp;#39;banana&amp;#39;,
  &amp;#39;cantaloupe&amp;#39;,
  &amp;#39;durian&amp;#39;,
  &amp;#39;eggplant&amp;#39;
];

const [, secondFruit,,, fifthFruit] = fruits;

console.log(secondFruit); // &amp;#39;banana&amp;#39;
console.log(fifthFruit); // &amp;#39;eggplant&amp;#39;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is an interesting little trick with destructuring assignment, but honestly I don&amp;#39;t know if it&amp;#39;s a great idea in complex cases like this. It feels simpler to me to use the standard notation:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;const secondFruit = fruits[1];
const fifthFruit = fruits[4];
&lt;/code&gt;&lt;/pre&gt;


&lt;h1&gt;06 JavaScript Modules&lt;/h1&gt;
&lt;p&gt;For a long time, JavaScript had no built-in module system.&lt;/p&gt;
&lt;p&gt;In the early days, we wrote our JavaScript programs in &lt;code&gt;.js&lt;/code&gt; files, and loaded them all up via &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; tags in our HTML files. This worked alright, but it meant that every script shared the same environment; variables declared in one file could be accessed in another. It was a bit of a mess.&lt;/p&gt;
&lt;p&gt;Several third-party solutions were invented, around 2009-2010. The most popular were RequireJS and CommonJS.&lt;/p&gt;
&lt;p&gt;Starting in the mid-2010s, however, JS got its own native module system! And it&amp;#39;s pretty cool.&lt;/p&gt;
&lt;h2&gt;Basic premise&lt;/h2&gt;
&lt;p&gt;When we work with a JS module system, every file becomes a &amp;quot;module&amp;quot;. A module is a JavaScript file that can contain one or more exports. We can pull the code from one module into another using the &lt;code&gt;import&lt;/code&gt; statement.&lt;/p&gt;
&lt;p&gt;If we don&amp;#39;t export a piece of data from one module, it won&amp;#39;t be available in any other modules. The only way to share anything between modules is through import/export.&lt;/p&gt;
&lt;p&gt;In addition to the code we write in our codebase, we can also import third-party modules like React.&lt;/p&gt;
&lt;p&gt;The benefit of this rather complex system is that everything is isolated by default. We have to go out of our way to share data between modules. Imports/exports are the &amp;quot;bridges&amp;quot; between modules, and by strategically placing them, we can make complex programs easier to reason about.&lt;/p&gt;
&lt;h2&gt;Named exports&lt;/h2&gt;
&lt;p&gt;Each file can define one or more named exports:&lt;/p&gt;

```javascript showLineNumbers
export const significantNum = 5;

&lt;p&gt;export function doubleNum(num) {
  return num * 2;
}&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;/CodeBlock&amp;gt;

In this case, our `data.js` module uses the `export` keyword to make a piece of data, `significantNum`, available to other files.

We&amp;#39;re also exporting a function, `doubleNum`. We can export any JavaScript data type, including functions and classes.

In our main file, `index.js`, we&amp;#39;re importing both of these exports:

&amp;lt;CodeBlock title=&amp;quot;index.js&amp;quot;&amp;gt;
```javascript showLineNumbers
import { significantNum, doubleNum } from &amp;#39;./data&amp;#39;;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;Inside the curly braces, we list each of the imports we want to bring in, by name. We don&amp;#39;t have to import all of the exports, we can pick just the ones we need.&lt;/p&gt;
&lt;p&gt;The string at the end, &lt;code&gt;&amp;#39;./data&amp;#39;&lt;/code&gt;, is the path to the module. We&amp;#39;re allowed to omit the &lt;code&gt;.js&lt;/code&gt; suffix, since it&amp;#39;s implied.&lt;/p&gt;
&lt;p&gt;The module system uses a linux-style relative path system to locate modules. A single dot, &lt;code&gt;.&lt;/code&gt;, refers to the same directory. Two dots, &lt;code&gt;..&lt;/code&gt;, refers to a parent directory.&lt;/p&gt;
&lt;h2&gt;Export statements&lt;/h2&gt;
&lt;p&gt;It&amp;#39;s conventional to export variables as they&amp;#39;re declared, like this:&lt;/p&gt;

```javascript showLineNumbers
export const significantNum = 5;
```


&lt;p&gt;It&amp;#39;s also possible to export previously-declared variables using squiggly brackets, like this:&lt;/p&gt;

```javascript showLineNumbers
const significantNum = 5;

&lt;p&gt;export { significantNum };&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;/CodeBlock&amp;gt;

Curiously, this syntax is quite rare — I only recently learned it was possible to do this! When it comes to named exports, it&amp;#39;s much more common to export them right when they&amp;#39;re declared.

We can also export functions as they&amp;#39;re declared, like this:

&amp;lt;CodeBlock title=&amp;quot;export-function&amp;quot;&amp;gt;
```javascript showLineNumbers
// Produces a named export called `someFunction`:
export function someFunction() { /* ... */ }
&lt;/code&gt;&lt;/pre&gt;


&lt;h2&gt;Renaming imports&lt;/h2&gt;
&lt;p&gt;Sometimes, we&amp;#39;ll run into naming collisions with named imports:&lt;/p&gt;

```javascript showLineNumbers
import { Wrapper } from &apos;./Header&apos;;
import { Wrapper } from &apos;./Footer&apos;;
// 🚫 Identifier &apos;Wrapper&apos; has already been declared.
```


&lt;p&gt;This happens because named exports don&amp;#39;t have to be globally unique. It&amp;#39;s perfectly valid for both Header and Footer to use the same name:&lt;/p&gt;

```javascript showLineNumbers
// Header.js
export function Wrapper() {
  return &lt;header&gt;Hello&lt;/header&gt;;
}

&lt;p&gt;// Footer.js
export function Wrapper() {
  return &lt;footer&gt;World&lt;/footer&gt;;
}&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;/CodeBlock&amp;gt;

We can rename imports with the `as` keyword:

&amp;lt;CodeBlock title=&amp;quot;renaming-imports&amp;quot;&amp;gt;
```javascript showLineNumbers
import { Wrapper as HeaderWrapper } from &amp;#39;./Header&amp;#39;;
import { Wrapper as FooterWrapper } from &amp;#39;./Footer&amp;#39;;
// ✅ No problems
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;Within the scope of this module, &lt;code&gt;HeaderWrapper&lt;/code&gt; will refer to the &lt;code&gt;Wrapper&lt;/code&gt; function exported from the &lt;code&gt;/Header.js&lt;/code&gt; module. Similarly, &lt;code&gt;FooterWrapper&lt;/code&gt; will refer to the other &lt;code&gt;Wrapper&lt;/code&gt; function exported from &lt;code&gt;/Footer.js&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;Default exports&lt;/h2&gt;
&lt;p&gt;There&amp;#39;s a separate type of export in JS modules: the default export.&lt;/p&gt;
&lt;p&gt;Let&amp;#39;s look at an example:&lt;/p&gt;

```javascript showLineNumbers
const magicNumber = 100;

&lt;p&gt;export default magicNumber;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;/CodeBlock&amp;gt;

When it comes to default exports, we always export an expression:

&amp;lt;CodeBlock title=&amp;quot;default-export-rules&amp;quot;&amp;gt;
```javascript showLineNumbers
// ✅ Correct:
const hi = 5;
export default hi;

// 🚫 Incorrect
export default const hi = 10;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;Every JS module is limited to a single default export. For example, this is invalid:&lt;/p&gt;

```javascript showLineNumbers
const hi = 5;
const bye = 10;

&lt;p&gt;export default hi;
export default bye;
// 🚫 SyntaxError: Too many default exports!&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;/CodeBlock&amp;gt;

When importing default exports, we don&amp;#39;t use squiggly brackets:

&amp;lt;CodeBlock title=&amp;quot;importing-default&amp;quot;&amp;gt;
```javascript showLineNumbers
// ✅ Correct:
import magicNumber from &amp;#39;./data&amp;#39;;

// 🚫 Incorrect:
import { magicNumber } from &amp;#39;./data&amp;#39;;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;When we&amp;#39;re importing a default export, we can name it whatever we want; it doesn&amp;#39;t have to match:&lt;/p&gt;

```javascript showLineNumbers
// ✅ This works
import magicNumber from &apos;./data&apos;;

&lt;p&gt;// ✅ This also works!
import helloWorld from &amp;#39;./data&amp;#39;;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;/CodeBlock&amp;gt;

A lot of these differences might seem arbitrary or confusing, but they all stem from this fact: Every module can have multiple named exports, but only a single default export.

For example, we need to use the correct name when importing a named export because we need to specify which export we want! But because there&amp;#39;s only a single default export, we can name it whatever we want, there&amp;#39;s no ambiguity.

## When to use which

Now that we&amp;#39;ve covered the fundamentals about named and default exports, you might be wondering: when should I use each type?

In fact, this is a question with no objectively &amp;quot;correct&amp;quot; answer. It all comes down to picking a convention that works for you.

For example, let&amp;#39;s say that we have a file that holds a bunch of theme constants (colors and sizes and fonts and stuff). We could structure it like this:

&amp;lt;CodeBlock title=&amp;quot;theme-default-export&amp;quot;&amp;gt;
```javascript showLineNumbers
const THEME = {
  colors: {
    red: &amp;#39;hsl(333deg 100% 45%)&amp;#39;,
    blue: &amp;#39;hsl(220deg 80% 40%)&amp;#39;,
  },
  spaces: [
    &amp;#39;0.25rem&amp;#39;,
    &amp;#39;0.5rem&amp;#39;,
    &amp;#39;1rem&amp;#39;,
    &amp;#39;1.5rem&amp;#39;,
    &amp;#39;2rem&amp;#39;,
    &amp;#39;4rem&amp;#39;,
    &amp;#39;8rem&amp;#39;,
  ],
  fonts: {
    default: &amp;#39;&amp;quot;Helvetica Neue&amp;quot;, sans-serif&amp;#39;,
    mono: &amp;#39;&amp;quot;Fira Code&amp;quot;, monospace&amp;#39;,
  },
}

export default THEME;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;Or, we could use named exports:&lt;/p&gt;

```javascript showLineNumbers
export const COLORS = {
  red: &apos;hsl(333deg 100% 45%)&apos;,
  blue: &apos;hsl(220deg 80% 40%)&apos;,
};

&lt;p&gt;export const SPACES = [
  &amp;#39;0.25rem&amp;#39;,
  &amp;#39;0.5rem&amp;#39;,
  &amp;#39;1rem&amp;#39;,
  &amp;#39;1.5rem&amp;#39;,
  &amp;#39;2rem&amp;#39;,
  &amp;#39;4rem&amp;#39;,
  &amp;#39;8rem&amp;#39;,
];&lt;/p&gt;
&lt;p&gt;export const FONTS = {
  default: &amp;#39;&amp;quot;Helvetica Neue&amp;quot;, sans-serif&amp;#39;,
  mono: &amp;#39;&amp;quot;Fira Code&amp;quot;, monospace&amp;#39;,
}&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;/CodeBlock&amp;gt;

We can use either a single &amp;quot;grouped&amp;quot; default export, or lots of individual named exports. Both of these options are perfectly valid.

Here&amp;#39;s a convention I like to follow, though: if a file has one obvious &amp;quot;main&amp;quot; thing, I make it the default export. Secondary things, like helpers and metadata, can be exported using named exports.

For example, a React component might be set up like this:

&amp;lt;CodeBlock title=&amp;quot;react-component-example&amp;quot;&amp;gt;
```javascript showLineNumbers
// components/Header.js
export const HEADER_HEIGHT = &amp;#39;5rem&amp;#39;;

function Header() {
  return (
    &amp;lt;header style={{ height: HEADER_HEIGHT }}&amp;gt;
      {/* Stuff here */}
    &amp;lt;/header&amp;gt;
  )
}

export default Header;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;The main &amp;quot;thing&amp;quot; in this &lt;code&gt;Header.js&lt;/code&gt; file is the &lt;code&gt;Header&lt;/code&gt; component, and so it uses the default export. Anything else will use named exports.&lt;/p&gt;
&lt;h1&gt;07 Array Iteration Methods&lt;/h1&gt;
&lt;p&gt;One of the novel things about React is that JSX doesn&amp;#39;t include any iteration helpers.&lt;/p&gt;
&lt;p&gt;In most templating languages, you have custom syntax like &lt;code&gt;{{#each}}&lt;/code&gt; to help you iterate through a set of data. In frameworks like Angular and Vue, you have directives like &lt;code&gt;v-for&lt;/code&gt; to manage iteration.&lt;/p&gt;
&lt;p&gt;React doesn&amp;#39;t provide any abstractions here, and so we&amp;#39;ll rely on the built-in methods that are part of the JavaScript language, methods like &lt;code&gt;map&lt;/code&gt; and &lt;code&gt;filter&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;If we can become comfortable with these core methods, we&amp;#39;ll have a much easier time doing iteration in React. In this section, we&amp;#39;ll learn about some of the most common and useful methods.&lt;/p&gt;
&lt;h2&gt;forEach&lt;/h2&gt;
&lt;p&gt;We use &lt;code&gt;forEach&lt;/code&gt; when we want to perform some sort of action on every item in an array.&lt;/p&gt;
&lt;p&gt;Here&amp;#39;s an example:&lt;/p&gt;

```javascript showLineNumbers
const pizzaToppings = [
  &apos;cheese&apos;,
  &apos;avocado&apos;,
  &apos;halibut&apos;,
  &apos;custard&apos;,
];

&lt;p&gt;pizzaToppings.forEach((topping) =&amp;gt; {
  console.log(topping);
});&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;/CodeBlock&amp;gt;

In this example, we&amp;#39;re logging the value of each topping, one at a time. Here&amp;#39;s what the console output would be:
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;cheese
avocado
halibut
custard&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;
The `forEach` method accepts a function as its argument. This is commonly known as a callback function.

The term &amp;quot;callback function&amp;quot; refers to a function that we pass to another function. In this case, we write an arrow function that looks like this:

&amp;lt;CodeBlock title=&amp;quot;callback-function&amp;quot;&amp;gt;
```javascript showLineNumbers
(topping) =&amp;gt; {
  console.log(topping);
}
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;We don&amp;#39;t call this function ourselves; instead, we pass it as an argument to the &lt;code&gt;forEach&lt;/code&gt; method. The JavaScript engine will call this function for us, supplying the &lt;code&gt;topping&lt;/code&gt; argument as it iterates over the array.&lt;/p&gt;
&lt;h2&gt;Accessing the index&lt;/h2&gt;
&lt;p&gt;The callback we pass to &lt;code&gt;forEach&lt;/code&gt; takes a second optional parameter:&lt;/p&gt;

```javascript showLineNumbers
const pizzaToppings = [
  &apos;cheese&apos;,
  &apos;avocado&apos;,
  &apos;halibut&apos;,
  &apos;custard&apos;,
];

&lt;p&gt;pizzaToppings.forEach((topping, index) =&amp;gt; {
  console.log(index, topping);
});&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;/CodeBlock&amp;gt;

The `index` is the position in the array of the current item, starting from 0. This code would log:
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;0 cheese
1 avocado
2 halibut
3 custard&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;
## A common format

JavaScript gives us several tools for iterating over the items in an array. We could have used a `for` loop, and it&amp;#39;s arguably much simpler. There are no complicated callback functions! So why should we learn about `.forEach`?

Here&amp;#39;s the biggest advantage: `forEach` is part of a family of array iteration methods. Taken as a whole, this family allows us to do all sorts of amazing things, like finding a particular item in the array, filtering a list, and much more.

All of the methods in this family follow the same basic structure. For example, they all support the optional `index` parameter we just looked at!

Let&amp;#39;s look at another member of this family: the `filter` method.

## filter

Things start to get really interesting with `filter`.

Here&amp;#39;s a quick example:

&amp;lt;CodeBlock title=&amp;quot;filter-example&amp;quot;&amp;gt;
```javascript showLineNumbers
const students = [
  { name: &amp;#39;Aisha&amp;#39;, grade: 89 },
  { name: &amp;#39;Bruno&amp;#39;, grade: 55 },
  { name: &amp;#39;Carlos&amp;#39;, grade: 68 },
  { name: &amp;#39;Dacian&amp;#39;, grade: 71 },
  { name: &amp;#39;Esther&amp;#39;, grade: 40 },
];

const studentsWhoPassed = students.filter(student =&amp;gt; {
  return student.grade &amp;gt;= 60;
});

console.log(studentsWhoPassed);
/*
  [
    { name: &amp;#39;Aisha&amp;#39;, grade: 89 },
    { name: &amp;#39;Carlos&amp;#39;, grade: 68 },
    { name: &amp;#39;Dacian&amp;#39;, grade: 71 },
  ]
*/
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;In many ways, &lt;code&gt;filter&lt;/code&gt; is very similar to &lt;code&gt;forEach&lt;/code&gt;. It takes a callback function, and that callback function will be called once per item in the array.&lt;/p&gt;
&lt;p&gt;Unlike &lt;code&gt;forEach&lt;/code&gt;, however, &lt;code&gt;filter&lt;/code&gt; produces a value. Specifically, it produces a new array which contains a subset of items from the original array.&lt;/p&gt;
&lt;p&gt;Typically, our callback function should return a boolean value, either &lt;code&gt;true&lt;/code&gt; or &lt;code&gt;false&lt;/code&gt;. The &lt;code&gt;filter&lt;/code&gt; method calls this function once for every item in the array. If the callback returns &lt;code&gt;true&lt;/code&gt;, this item is included in the new array. Otherwise, it&amp;#39;s excluded.&lt;/p&gt;
&lt;p&gt;Important to note: The &lt;code&gt;filter&lt;/code&gt; method doesn&amp;#39;t modify the original array. This is true for all of the array methods discussed in this lesson.&lt;/p&gt;
&lt;p&gt;Here&amp;#39;s one more example:&lt;/p&gt;

```javascript showLineNumbers
const nums = [5, 12, 15, 31, 40];

&lt;p&gt;const evenNums = nums.filter(num =&amp;gt; {
  return num % 2 === 0;
});&lt;/p&gt;
&lt;p&gt;console.log(nums); // Hasn&amp;#39;t changed: [5, 12, 15, 31, 40]
console.log(evenNums); // [12, 40]&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;/CodeBlock&amp;gt;

## map

Finally, we have the `map` method. This is the most commonly-used array method, when working with React.

Let&amp;#39;s start with an example:

&amp;lt;CodeBlock title=&amp;quot;map-example&amp;quot;&amp;gt;
```javascript showLineNumbers
const people = [
  { name: &amp;#39;Aisha&amp;#39;, grade: 89 },
  { name: &amp;#39;Bruno&amp;#39;, grade: 55 },
  { name: &amp;#39;Carlos&amp;#39;, grade: 68 },
  { name: &amp;#39;Dacian&amp;#39;, grade: 71 },
  { name: &amp;#39;Esther&amp;#39;, grade: 40 },
];

const screamedNames = people.map(person =&amp;gt; {
  return person.name.toUpperCase();
});

console.log(screamedNames);
/*
  [&amp;#39;AISHA&amp;#39;, &amp;#39;BRUNO&amp;#39;, &amp;#39;CARLOS&amp;#39;, &amp;#39;DACIAN&amp;#39;, &amp;#39;ESTHER&amp;#39;]
*/
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;In many ways, &lt;code&gt;map&lt;/code&gt; is quite a lot like &lt;code&gt;forEach&lt;/code&gt;. We give it a callback function, and it iterates over the array, calling the function once for each item in the array.&lt;/p&gt;
&lt;p&gt;Here&amp;#39;s the big difference, though: &lt;code&gt;map&lt;/code&gt; produces a brand new array, full of transformed values.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;forEach&lt;/code&gt; function will always return &lt;code&gt;undefined&lt;/code&gt;:&lt;/p&gt;

```javascript showLineNumbers
const nums = [1, 2, 3];

&lt;p&gt;const result = nums.forEach(num =&amp;gt; num + 1);&lt;/p&gt;
&lt;p&gt;console.log(result); // undefined&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;/CodeBlock&amp;gt;

By contrast, `map` will &amp;quot;collect&amp;quot; all the values we return from our callback, and put them into a new array:

&amp;lt;CodeBlock title=&amp;quot;map-returns-array&amp;quot;&amp;gt;
```javascript showLineNumbers
const nums = [1, 2, 3];

const result = nums.map(num =&amp;gt; num + 1);

console.log(result); // [2, 3, 4]
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;Like &lt;code&gt;filter&lt;/code&gt;, &lt;code&gt;map&lt;/code&gt; doesn&amp;#39;t mutate the original array; it produces a brand-new array.&lt;/p&gt;
&lt;p&gt;Also, the new array will always have the exact same length as the original array. We can&amp;#39;t &amp;quot;skip&amp;quot; certain items by returning &lt;code&gt;false&lt;/code&gt; or not returning anything at all:&lt;/p&gt;

```javascript showLineNumbers
const people = [
  { id: &apos;a&apos;, name: &apos;Aisha&apos; },
  { id: &apos;b&apos; },
  { id: &apos;c&apos; },
  { id: &apos;d&apos;, name: &apos;Dacian&apos; },
  { id: &apos;e&apos; },
];

&lt;p&gt;const screamedNames = people.map(person =&amp;gt; {
  if (person.name) {
    return person.name.toUpperCase();
  }
});&lt;/p&gt;
&lt;p&gt;console.log(screamedNames);
/*
  [&amp;#39;AISHA&amp;#39;, undefined, undefined, &amp;#39;DACIAN&amp;#39;, undefined]
*/&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;/CodeBlock&amp;gt;

Here&amp;#39;s a helpful way to think about `map`: it&amp;#39;s exactly like `forEach`, except it &amp;quot;saves&amp;quot; whatever we return from the callback into a new array.

## Accessing the index with map

Like the other methods we&amp;#39;ve seen, we can pass a second parameter to access the current item&amp;#39;s index:

&amp;lt;CodeBlock title=&amp;quot;map-with-index&amp;quot;&amp;gt;
```javascript showLineNumbers
const people = [
  { name: &amp;#39;Aisha&amp;#39;, grade: 89 },
  { name: &amp;#39;Bruno&amp;#39;, grade: 55 },
  { name: &amp;#39;Carlos&amp;#39;, grade: 68 },
  { name: &amp;#39;Dacian&amp;#39;, grade: 71 },
  { name: &amp;#39;Esther&amp;#39;, grade: 40 },
];

const numberedNames = people.map((person, index) =&amp;gt; {
  return `${index}-${person.name}`;
});

console.log(numberedNames);
/*
  [&amp;#39;0-Aisha&amp;#39;, &amp;#39;1-Bruno&amp;#39;, &amp;#39;2-Carlos&amp;#39;, &amp;#39;3-Dacian&amp;#39;, &amp;#39;4-Esther&amp;#39;]
*/
&lt;/code&gt;&lt;/pre&gt;


&lt;h2&gt;Additional methods&lt;/h2&gt;
&lt;p&gt;We&amp;#39;ve seen 3 of the most common methods here, but there are actually several more that follow this same format, including &lt;code&gt;find&lt;/code&gt; (selecting a single item from the array), &lt;code&gt;every&lt;/code&gt; (checking if all items in an array fulfill some condition), and &lt;code&gt;reduce&lt;/code&gt; (combine all items in the array into a single final value).&lt;/p&gt;
&lt;p&gt;You can learn more about these methods on MDN.&lt;/p&gt;
&lt;h1&gt;08 Truthy and Falsy&lt;/h1&gt;
&lt;p&gt;Let&amp;#39;s consider the following JavaScript statement:&lt;/p&gt;

```javascript showLineNumbers
const user = {
  name: &apos;J. Script&apos;,
};

&lt;p&gt;if (user.name) {
  console.log(&amp;#39;This user has a name!&amp;#39;);
}&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;/CodeBlock&amp;gt;

We have a user object, and we want to run a `console.log` depending on a condition. The condition is the JavaScript expression `user.name`.

Interestingly, `user.name` isn&amp;#39;t a boolean value. The user&amp;#39;s name is neither `true` nor `false`. In many programming languages, this would be an illegal operation. How should the language know if some random string is sufficient or not??

In JavaScript, every value is either &amp;quot;truthy&amp;quot; or &amp;quot;falsy&amp;quot;. A truthy value is one that counts as `true` when it comes to conditions.

Most values in JavaScript are truthy. It&amp;#39;s faster to list all of the falsy values:

- `false`
- `null`
- `undefined`
- `&amp;#39;&amp;#39;` (empty string)
- `0` (and related values, like `0.0` and `-0`)
- `NaN`

In the code above, `user.name` is a truthy value, because it&amp;#39;s a string with at least 1 character. Every string other than `&amp;#39;&amp;#39;` is truthy.

Somewhat surprisingly, `[]` (empty array) and `{}` (empty object) are truthy values, not falsy. This means that every object/array is truthy.

## Converting to boolean

Sometimes, it&amp;#39;s beneficial to convert a truthy value into `true`, or a falsy value into `false`.

The most declarative way to do this is to use the `Boolean()` constructor:

&amp;lt;CodeBlock title=&amp;quot;boolean-constructor&amp;quot;&amp;gt;
```javascript showLineNumbers
Boolean(4); // true
Boolean(0); // false
Boolean([]); // true
Boolean(&amp;#39;&amp;#39;); // false
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;There&amp;#39;s another more-common way to convert to boolean. And, if you&amp;#39;re not familiar with it, it can look a bit funky:&lt;/p&gt;

```javascript showLineNumbers
!!4; // true
!!0; // false
!![]; // true
!!&apos;&apos;; // false
```


&lt;p&gt;&lt;code&gt;!!&lt;/code&gt; isn&amp;#39;t actually a JavaScript operator; we&amp;#39;re repeating the NOT operator (&lt;code&gt;!&lt;/code&gt;) twice.&lt;/p&gt;
&lt;p&gt;We can use &lt;code&gt;!&lt;/code&gt; to flip a boolean value:&lt;/p&gt;

```javascript showLineNumbers
!true; // false
!false; // true
```


&lt;p&gt;If we use the &lt;code&gt;!&lt;/code&gt; with a non-boolean value, it will flip a truthy value to &lt;code&gt;false&lt;/code&gt;, or a falsy value to &lt;code&gt;true&lt;/code&gt;:&lt;/p&gt;

```javascript showLineNumbers
!4; // false, since 4 is truthy
!0; // true, since 0 is falsy
```


&lt;p&gt;We can stack multiple &lt;code&gt;!&lt;/code&gt; operators to flip it back and forth:&lt;/p&gt;

```javascript showLineNumbers
!4; // false
!!4; // true
!!!4; // false
!!!!4; // true
```


&lt;p&gt;To break down what&amp;#39;s going on here: Each &lt;code&gt;!&lt;/code&gt; is evaluated, one at a time. It&amp;#39;s as if there were parens around each set, like this:&lt;/p&gt;

```javascript showLineNumbers
!(!(!4))
    ^^ !4 resolves to `false`

&lt;p&gt;!(!false)
  ^^^^^^ !false resolves to &lt;code&gt;true&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;!true
^^^^^ !true resolves to &lt;code&gt;false&lt;/code&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;/CodeBlock&amp;gt;

I&amp;#39;m not sure why `!!` has become the de facto standard way of converting to boolean; the `Boolean()` constructor seems a lot more intuitive to me!

# 09 Logical Operators

If you&amp;#39;ve been working with JavaScript for a while, you&amp;#39;re probably already familiar with the AND operator (`&amp;amp;&amp;amp;`) and the OR operator (`||`):

&amp;lt;CodeBlock title=&amp;quot;basic-logical-operators&amp;quot;&amp;gt;
```javascript showLineNumbers
const isLoggedIn = true;
const userRole = &amp;#39;administrator&amp;#39;;

if (isLoggedIn &amp;amp;&amp;amp; userRole === &amp;#39;administrator&amp;#39;) {
  // This code only runs if BOTH conditions above are truthy
}
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;There&amp;#39;s something that many JavaScript developers don&amp;#39;t realize about these operators, however: they also act as control flow operators.&lt;/p&gt;
&lt;p&gt;Let&amp;#39;s test your knowledge with a quick multiple-choice question: What is the value of &lt;code&gt;result&lt;/code&gt;?&lt;/p&gt;

```javascript showLineNumbers
const myAge = 35;
const result = myAge &lt; 50 &amp;&amp; myAge;
```


&lt;ol&gt;
&lt;li&gt;&lt;code&gt;true&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;false&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;35&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;None of the above&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;It is totally reasonable to expect that the answer would be &lt;code&gt;true&lt;/code&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;myAge &amp;lt; 50&lt;/code&gt; resolves to &lt;code&gt;true&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;myAge&lt;/code&gt; resolves to &lt;code&gt;35&lt;/code&gt;, which is a truthy value&lt;/li&gt;
&lt;li&gt;If both sides are truthy, the whole thing should evaluate to &lt;code&gt;true&lt;/code&gt;, right?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Afraid not! The &lt;code&gt;&amp;amp;&amp;amp;&lt;/code&gt; operator isn&amp;#39;t designed to produce a boolean value. It&amp;#39;s designed to resolve to one of the expressions on either side of the operator.&lt;/p&gt;
&lt;p&gt;You can think of &lt;code&gt;&amp;amp;&amp;amp;&lt;/code&gt; like a gate. We&amp;#39;re allowed to move through the gate if the left-hand side is truthy.&lt;/p&gt;
&lt;p&gt;This becomes clearer when we chain multiple &lt;code&gt;&amp;amp;&amp;amp;&lt;/code&gt;s together:&lt;/p&gt;

```javascript showLineNumbers
const numOfChildren = 4;
const parkingHasBeenValidated = true;
const signatureOnWaiver = &apos;&apos;;

&lt;p&gt;const admissionTicket =
  numOfChildren &amp;amp;&amp;amp;
  parkingHasBeenValidated &amp;amp;&amp;amp;
  signatureOnWaiver &amp;amp;&amp;amp;
  generateTicket();&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;/CodeBlock&amp;gt;

The first expression in this chain is `numOfChildren`, which is `4`. This is a truthy value, and so the first `&amp;amp;&amp;amp;` gate is unlocked.

The second expression is `parkingHasBeenValidated`, which is `true`. We move through the second gate.

The third expression, `signatureOnWaiver`, is an empty string (`&amp;#39;&amp;#39;`), which is falsy. This means that the third `&amp;amp;&amp;amp;` gate stays locked. We can&amp;#39;t go any further. The current expression, `&amp;#39;&amp;#39;`, is what gets resolved.

As a result, `admissionTicket` would be assigned `&amp;#39;&amp;#39;`. Not `false`.

Let&amp;#39;s suppose `signatureOnWaiver` wasn&amp;#39;t an empty string:

&amp;lt;CodeBlock title=&amp;quot;all-truthy-and-chain&amp;quot;&amp;gt;
```javascript showLineNumbers
const numOfChildren = 4;
const parkingHasBeenValidated = true;
const signatureOnWaiver = &amp;#39;Becky Chambers&amp;#39;;

const admissionTicket =
  numOfChildren &amp;amp;&amp;amp;
  parkingHasBeenValidated &amp;amp;&amp;amp;
  signatureOnWaiver &amp;amp;&amp;amp;
  generateTicket();
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;Now, when we get to the third expression, we get a truthy value (the string &amp;quot;Becky Chambers&amp;quot;). The final gate is unlocked.&lt;/p&gt;
&lt;p&gt;Because all of the gates are unlocked, the final expression will be passed along. &lt;code&gt;admissionTicket&lt;/code&gt; will be equal to whatever the &lt;code&gt;generateTicket&lt;/code&gt; function returns.&lt;/p&gt;
&lt;p&gt;Here&amp;#39;s how we&amp;#39;d set up exactly the same code, but using &lt;code&gt;if&lt;/code&gt;/&lt;code&gt;else&lt;/code&gt; instead of logical operators:&lt;/p&gt;

```javascript showLineNumbers
let admissionTicket;

&lt;p&gt;if (!numOfChildren) {
  admissionTicket = numOfChildren;
} else if (!parkingHasBeenValidated) {
  admissionTicket = parkingHasBeenValidated;
} else if (!signatureOnWaiver) {
  admissionTicket = signatureOnWaiver;
} else {
  admissionTicket = generateTicket();
}&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;/CodeBlock&amp;gt;

`admissionTicket` will be assigned to the first falsy expression. If we make it through all of the gates, `admissionTicket` will be assigned to the final expression, whether it&amp;#39;s truthy or falsy.

There&amp;#39;s one more interesting takeaway here: The `generateTicket` function is only called if we make it through all the gates. In the first example, when `signatureOnWaiver` was falsy, the `generateTicket` function was never called.

This is because of short-circuiting. If one of the expressions before an `&amp;amp;&amp;amp;` operator evaluates to a falsy value, the rest of the expressions are skipped. They won&amp;#39;t be executed at all.

Here&amp;#39;s a less-complex example:

&amp;lt;CodeBlock title=&amp;quot;short-circuiting-example&amp;quot;&amp;gt;
```javascript showLineNumbers
false &amp;amp;&amp;amp; console.log(&amp;#39;I will never run&amp;#39;);
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;Because &lt;code&gt;false&lt;/code&gt; is a falsy value, the &lt;code&gt;&amp;amp;&amp;amp;&lt;/code&gt; gate remains locked, and the &lt;code&gt;console.log&lt;/code&gt; never fires. It&amp;#39;s the same as if the &lt;code&gt;console.log&lt;/code&gt; was within an &lt;code&gt;if&lt;/code&gt; statement:&lt;/p&gt;

```javascript showLineNumbers
if (false) {
  console.log(&apos;I will never run&apos;);
}
```


&lt;h2&gt;The OR operator&lt;/h2&gt;
&lt;p&gt;The &lt;code&gt;||&lt;/code&gt; operator is exactly like the &lt;code&gt;&amp;amp;&amp;amp;&lt;/code&gt; operator, with one key difference: &lt;code&gt;||&lt;/code&gt; doesn&amp;#39;t stop and provide the first falsy value. It stops and provides the first truthy value.&lt;/p&gt;
&lt;p&gt;For example:&lt;/p&gt;

```javascript showLineNumbers
const userImageSrc = null;
const teamImageSrc = null;
const defaultImageSrc = &apos;/images/cat.jpg&apos;;

&lt;p&gt;const src = userImageSrc || teamImageSrc || defaultImageSrc;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;/CodeBlock&amp;gt;

We check the first expression, `userImageSrc`, which is `null`. Because it&amp;#39;s falsy, the `||` gate is unlocked, and we proceed onwards.

The second expression, `teamImageSrc`, is also `null`, and so the second `||` gate unlocks.

As with `&amp;amp;&amp;amp;`, when we make it to the final item, the final item is provided regardless of whether it&amp;#39;s truthy or falsy. And so `src` will be assigned to `defaultImageSrc`.

However, in this case:

&amp;lt;CodeBlock title=&amp;quot;or-operator-truthy-example&amp;quot;&amp;gt;
```javascript showLineNumbers
const userImageSrc = &amp;#39;/images/my-avatar.png&amp;#39;;
const teamImageSrc = null;
const defaultImageSrc = &amp;#39;/images/cat.jpg&amp;#39;;

const src = userImageSrc || teamImageSrc || defaultImageSrc;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;The first item, &lt;code&gt;userImageSrc&lt;/code&gt;, is truthy! Because it&amp;#39;s truthy, the first &lt;code&gt;||&lt;/code&gt; gate remains locked, and &lt;code&gt;src&lt;/code&gt; is assigned to &lt;code&gt;userImageSrc&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Here&amp;#39;s how we&amp;#39;d represent this code using &lt;code&gt;if&lt;/code&gt;/&lt;code&gt;else&lt;/code&gt;:&lt;/p&gt;

```javascript showLineNumbers
let src;

&lt;p&gt;if (userImageSrc) {
  src = userImageSrc;
} else if (teamImageSrc) {
  src = teamImageSrc;
} else {
  src = defaultImageSrc;
}&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;/CodeBlock&amp;gt;

# 10 Assignment Vs. Mutation

in progress...

# 11 Rest / Spread

in progress...

# 12 Intervals and Timeouts

in progress...

# 13 Global Events

in progress...

# 14 Async / Await

in progress...

# 15 HTTP Methods

in progress...

# Fetch

in progress...

# 16 HTTP Status Codes

in progress...
&lt;/code&gt;&lt;/pre&gt;
]]></content:encoded>
            <dc:creator>Rami Chabchoub</dc:creator>
        </item>
        <item>
            <title><![CDATA[Introduction to Laravel InertiaJS ReactJS]]></title>
            <description><![CDATA[Complete guide to building modern web applications with Laravel, Inertia.js, and React]]></description>
            <link>https://www.ramicode.com/en/articles/laravel-inertiajs-reactjs</link>
            <guid isPermaLink="false">laravel-inertiajs-reactjs</guid>
            <dc:creator><![CDATA[Rami Chabchoub]]></dc:creator>
            <pubDate>Sat, 07 Jun 2025 00:00:00 GMT</pubDate>
            <content:encoded><![CDATA[&lt;p&gt;This comprehensive guide will walk you through building a modern web application using Laravel as the backend, Inertia.js as the bridge, and React for the frontend. We&amp;#39;ll create a complete product management system from scratch.&lt;/p&gt;
&lt;h1&gt;Laravel Installation and Setup&lt;/h1&gt;
&lt;p&gt;Let&amp;#39;s start by setting up a new Laravel project. There are several ways to create a Laravel application:&lt;/p&gt;

```bash showLineNumbers
# Install global laravel installer
composer global require laravel/installer

&lt;h1&gt;Create a new Laravel project&lt;/h1&gt;
&lt;p&gt;laravel new introduction&lt;/p&gt;
&lt;h1&gt;Alternative: using composer&lt;/h1&gt;
&lt;p&gt;composer create-project laravel/laravel introduction&lt;/p&gt;
&lt;h1&gt;Run the development server&lt;/h1&gt;
&lt;p&gt;php artisan serve
npm run dev&lt;/p&gt;
&lt;h1&gt;Run both with single command (using concurrently, open composer.json)&lt;/h1&gt;
&lt;p&gt;composer dev&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;/CodeBlock&amp;gt;

The Laravel installer provides various options including Docker Sail and starter kits like Breeze with Blade or Livewire templates.

## Docker Setup with PostgreSQL

For a consistent development environment, let&amp;#39;s set up Docker with PostgreSQL. Create a `docker-compose.yml` file in your project root:

&amp;lt;CodeBlock title=&amp;quot;docker-compose.yml&amp;quot;&amp;gt;
```yaml showLineNumbers
services:
  db:
    image: postgres:17
    container_name: advantryx_introduction_db
    restart: unless-stopped
    environment:
      POSTGRES_DB: advantryx_introduction
      POSTGRES_USER: laravel
      POSTGRES_PASSWORD: password
      POSTGRES_ROOT_PASSWORD: admin
    ports:
      - &amp;#39;5432:5432&amp;#39;
    volumes:
      - postgres_data:/var/lib/postgresql/data
    networks:
      - advantryx_introduction

networks:
  advantryx_introduction:
    driver: bridge

volumes:
  postgres_data:
    driver: local
&lt;/code&gt;&lt;/pre&gt;


&lt;h2&gt;Database Configuration&lt;/h2&gt;
&lt;p&gt;Update your &lt;code&gt;.env&lt;/code&gt; file with the PostgreSQL database configuration:&lt;/p&gt;

```bash showLineNumbers
DB_CONNECTION=pgsql
DB_HOST=127.0.0.1
DB_PORT=5432
DB_DATABASE=advantryx_introduction
DB_USERNAME=laravel
DB_PASSWORD=password
```


&lt;p&gt;Start your PostgreSQL container:&lt;/p&gt;

```bash showLineNumbers
# Start the PostgreSQL container
docker-compose up -d

&lt;h1&gt;Check if the container is running&lt;/h1&gt;
&lt;p&gt;docker-compose ps&lt;/p&gt;
&lt;h1&gt;View container logs&lt;/h1&gt;
&lt;p&gt;docker-compose logs db&lt;/p&gt;
&lt;h1&gt;Stop the container when done&lt;/h1&gt;
&lt;p&gt;docker-compose down&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;/CodeBlock&amp;gt;

# Laravel Basics and Creating Products with Routes and Controllers

## Understanding Laravel Core Concepts

Before diving into code, let&amp;#39;s understand the key Laravel components:

**Models** provide a powerful and enjoyable interface for you to interact with the tables in your database.

**Migrations** allow you to easily create and modify the tables in your database. They ensure that the same database structure exists everywhere that your application runs.

**Controllers** are responsible for processing requests made to your application and returning a response.

## Creating Products with Routes and Controllers

Let&amp;#39;s create a Product model with migration, controller, and resource routes:

&amp;lt;CodeBlock title=&amp;quot;create-product-model&amp;quot;&amp;gt;
```bash showLineNumbers
php artisan make:model Product -mcr
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;This command creates:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Model: &lt;code&gt;app/Models/Product.php&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Migration: &lt;code&gt;database/migrations/xxxx_create_products_table.php&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Controller: &lt;code&gt;app/Http/Controllers/ProductController.php&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Resource routes (we&amp;#39;ll add manually)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Now let&amp;#39;s set up the routes:&lt;/p&gt;

```php showLineNumbers
Route::resource(&apos;products&apos;, ProductController::class)
    -&gt;only([&apos;index&apos;, &apos;store&apos;]);

&lt;p&gt;// Alternative individual routes:
// Route::get(&amp;#39;/products&amp;#39;, [ProductController::class, &amp;#39;index&amp;#39;])-&amp;gt;name(&amp;#39;products.index&amp;#39;);
// Route::post(&amp;#39;/products&amp;#39;, [ProductController::class, &amp;#39;store&amp;#39;])-&amp;gt;name(&amp;#39;products.store&amp;#39;);&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;/CodeBlock&amp;gt;

You can verify your routes using these commands:

&amp;lt;CodeBlock title=&amp;quot;route-list&amp;quot;&amp;gt;
```bash showLineNumbers
php artisan route:list
php artisan route:list --path=products
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;Let&amp;#39;s update the ProductController to return a basic response:&lt;/p&gt;

```php showLineNumbers {7, 14, 16}
&lt;?php
 ...
namespace App\Http\Controllers;

&lt;p&gt;use App\Models\Product;
use Illuminate\Http\Request;
use Illuminate\Http\Response;&lt;/p&gt;
&lt;p&gt;class ProductController extends Controller
{
    /**
     * Display a listing of the resource.
     */
    public function index(): Response
    {
        return response(&amp;#39;Hello, World!&amp;#39;);
    }
 ...
}&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;/CodeBlock&amp;gt;

Now let&amp;#39;s integrate Inertia.js to render React components:

&amp;lt;CodeBlock title=&amp;quot;app/Http/Controllers/ProductController.php&amp;quot;&amp;gt;
```php showLineNumbers {8, 17}
&amp;lt;?php

namespace App\Http\Controllers;

use App\Models\Product;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Inertia\Inertia;

class ProductController extends Controller
{
    /**
     * Display a listing of the resource.
     */
    public function index(): Response
    {
        return Inertia::render(&amp;#39;Products/Index&amp;#39;);
    }
}
&lt;/code&gt;&lt;/pre&gt;


&lt;h1&gt;Frontend Setup with Inertia.js and React&lt;/h1&gt;
&lt;p&gt;Now that we have our backend set up, let&amp;#39;s create the React frontend component that will handle product creation.&lt;/p&gt;
&lt;h2&gt;Creating the Products Index Component&lt;/h2&gt;
&lt;p&gt;Create the React component that will be rendered by our Inertia controller:&lt;/p&gt;

```jsx showLineNumbers
import AppLayout from &apos;@/layouts/app-layout&apos;;
import InputError from &apos;@/components/input-error&apos;;
import { Button } from &apos;@/components/ui/button&apos;;
import { Input } from &apos;@/components/ui/input&apos;;
import { useForm, Head } from &apos;@inertiajs/react&apos;;
import { FormEventHandler } from &apos;react&apos;;

&lt;p&gt;export default function Index() {
    const { data, setData, post, processing, reset, errors } = useForm({
        name: &amp;#39;&amp;#39;,
    });&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const submit: FormEventHandler = (e) =&amp;gt; {
    e.preventDefault();
    post(route(&amp;#39;products.store&amp;#39;), { onSuccess: () =&amp;gt; reset() });
};

return (
    &amp;lt;AppLayout&amp;gt;
        &amp;lt;Head title=&amp;quot;Products&amp;quot; /&amp;gt;

        &amp;lt;div className=&amp;quot;mx-auto max-w-2xl p-4 sm:p-6 lg:p-8&amp;quot;&amp;gt;
            &amp;lt;form onSubmit={submit}&amp;gt;
                &amp;lt;Input
                    value={data.name}
                    placeholder=&amp;quot;Name of the product&amp;quot;
                    onChange={(e) =&amp;gt; setData(&amp;#39;name&amp;#39;, e.target.value)}
                /&amp;gt;
                &amp;lt;InputError message={errors.name} className=&amp;quot;mt-2&amp;quot; /&amp;gt;
                &amp;lt;Button className=&amp;quot;mt-4&amp;quot; disabled={processing}&amp;gt;
                    Create
                &amp;lt;/Button&amp;gt;
            &amp;lt;/form&amp;gt;
        &amp;lt;/div&amp;gt;
    &amp;lt;/AppLayout&amp;gt;
);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;}&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;/CodeBlock&amp;gt;

This component demonstrates several key Inertia.js and React concepts:

- **useForm hook**: Manages form state, submission, and validation errors
- **Head component**: Sets the page title
- **route() helper**: Generates URLs for named routes
- **Form handling**: Prevents default submission and uses Inertia&amp;#39;s post method

## Adding Navigation

To make the products page accessible, let&amp;#39;s add it to the sidebar navigation:

&amp;lt;CodeBlock title=&amp;quot;resources/js/components/app-sidebar.tsx&amp;quot;&amp;gt;
```tsx showLineNumbers {3-7}
// resources/js/components/app-sidebar.tsx
const mainNavItems: NavItem[] = [
    {
        title: &amp;#39;Products&amp;#39;,
        href: &amp;#39;/products&amp;#39;,
        icon: Package,
    },
];
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;This adds a &amp;quot;Products&amp;quot; link to your application&amp;#39;s sidebar with a Package icon.&lt;/p&gt;
&lt;h1&gt;Database Relationships and Eloquent&lt;/h1&gt;
&lt;p&gt;Now let&amp;#39;s set up proper database relationships and implement the store functionality for our products.&lt;/p&gt;
&lt;h2&gt;Setting Up the Database Migration&lt;/h2&gt;
&lt;p&gt;First, let&amp;#39;s update our products migration to include the necessary fields and foreign key relationships:&lt;/p&gt;

```php showLineNumbers {12-15}
&lt;?php
 ...
return new class extends Migration
{
    /**
     * Run the migrations.
     */
    public function up(): void
    {
        Schema::create(&apos;products&apos;, function (Blueprint $table) {
            $table-&gt;id();
            $table-&gt;foreignId(&apos;user_id&apos;)-&gt;constrained()-&gt;cascadeOnDelete(); // Shorthand
            // $table-&gt;unsignedBigInteger(&apos;user_id&apos;);
            // $table-&gt;foreign(&apos;user_id&apos;)-&gt;references(&apos;id&apos;)-&gt;on(&apos;users&apos;)-&gt;onDelete(&apos;cascade&apos;);
            $table-&gt;string(&apos;name&apos;);
            $table-&gt;timestamps();
        });
    }
 ...
};
```


&lt;h2&gt;Implementing the Store Method&lt;/h2&gt;
&lt;p&gt;Let&amp;#39;s update our ProductController to handle product creation with proper validation:&lt;/p&gt;

```php showLineNumbers {17, 19-25}
&lt;?php

&lt;p&gt;namespace App\Http\Controllers;&lt;/p&gt;
&lt;p&gt;use App\Models\Product;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Inertia\Inertia;
use Inertia\Response;&lt;/p&gt;
&lt;p&gt;class ProductController extends Controller
{
 ...
    /**
     * Store a newly created resource in storage.
     */
    public function store(Request $request): RedirectResponse
    {
        $validated = $request-&amp;gt;validate([
            &amp;#39;name&amp;#39; =&amp;gt; &amp;#39;required|string|max:255&amp;#39;,
        ]);&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    $request-&amp;gt;user()-&amp;gt;products()-&amp;gt;create($validated);

    return redirect(route(&amp;#39;products.index&amp;#39;));
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt; ...
}&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;/CodeBlock&amp;gt;

## Setting Up Eloquent Relationships

Now let&amp;#39;s define the relationships between User and Product models. Check out the &amp;lt;A href=&amp;quot;https://laravel.com/docs/12.x/eloquent-relationships&amp;quot;&amp;gt;Eloquent Relationships documentation&amp;lt;/A&amp;gt; for more details.

### User Model Relationship

&amp;lt;CodeBlock title=&amp;quot;user-model-relationship&amp;quot;&amp;gt;
```php showLineNumbers {3, 11-14}
&amp;lt;?php
 ...
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Laravel\Sanctum\HasApiTokens;

class User extends Authenticatable
{
 ...
    public function products(): HasMany
    {
        return $this-&amp;gt;hasMany(Product::class);
    }
}
&lt;/code&gt;&lt;/pre&gt;


&lt;h3&gt;Product Model Configuration&lt;/h3&gt;

```php showLineNumbers
&lt;?php

&lt;p&gt;class Product extends Model
{
    protected $fillable = [&amp;#39;name&amp;#39;];
    // protected $guarded = []; // if you want to allow all fields (not recommended)
}&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;/CodeBlock&amp;gt;

## Running Migrations

&amp;lt;CodeBlock title=&amp;quot;migration-commands&amp;quot;&amp;gt;
```bash showLineNumbers
php artisan migrate
php artisan migrate:rollback
&lt;/code&gt;&lt;/pre&gt;



During development, you can add new database fields without creating a new migration file by modifying the existing migration before running it.


&lt;p&gt;You can test your models using Laravel Tinker:&lt;/p&gt;

```bash showLineNumbers
php artisan tinker
App\Models\Product::all();
```


&lt;h1&gt;Displaying Products&lt;/h1&gt;
&lt;p&gt;Now that we have our database relationships set up, let&amp;#39;s implement the functionality to display products with their associated user information.&lt;/p&gt;
&lt;h2&gt;Updating the Controller to Fetch Products&lt;/h2&gt;
&lt;p&gt;Let&amp;#39;s modify our ProductController to fetch products with their related user data:&lt;/p&gt;

```php showLineNumbers {11}
&lt;?php
 ...
class ProductController extends Controller
{
    /**
     * Display a listing of the resource.
     */
    public function index(): Response
    {
        return Inertia::render(&apos;Products/Index&apos;, [
            &apos;products&apos; =&gt; Product::with(&apos;user:id,name&apos;)-&gt;latest()-&gt;get(),
        ]);
    }
 ...
}
```


&lt;h2&gt;Adding Product Model Relationship&lt;/h2&gt;
&lt;p&gt;We need to add the belongsTo relationship in our Product model:&lt;/p&gt;

```php showLineNumbers {2, 6-9}
&lt;?php
use Illuminate\Database\Eloquent\Relations\BelongsTo;
 ...
class Product extends Model
{
    public function user(): BelongsTo
    {
        return $this-&gt;belongsTo(User::class);
    }
}
```


&lt;h2&gt;Creating the Product Component&lt;/h2&gt;
&lt;p&gt;Let&amp;#39;s create a reusable Product component to display individual products:&lt;/p&gt;

```jsx showLineNumbers
// resources/js/components/Product.tsx
import { User } from &apos;lucide-react&apos;;

&lt;p&gt;export interface ProductProps {
    id: number;
    name: string;
    user: {
        name: string;
    };
    created_at: string;
}&lt;/p&gt;
&lt;p&gt;export default function Product(product: ProductProps) {
    return (
        &lt;div className=&quot;flex space-x-2 p-6&quot;&gt;
            
            &lt;div className=&quot;flex-1&quot;&gt;
                &lt;div className=&quot;flex items-center justify-between&quot;&gt;
                    &lt;div&gt;
                        &lt;span className=&quot;text-gray-800&quot;&gt;{product.user.name}&lt;/span&gt;
                        &lt;small className=&quot;ml-2 text-sm text-gray-600&quot;&gt;{new Date(product.created_at).toLocaleString()}&lt;/small&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
                &lt;p className=&quot;mt-4 text-lg text-gray-900&quot;&gt;{product.name}&lt;/p&gt;
            &lt;/div&gt;
        &lt;/div&gt;
    );
}&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;/CodeBlock&amp;gt;

## Updating the Index Page

Now let&amp;#39;s update our Products Index page to display the list of products:

&amp;lt;CodeBlock title=&amp;quot;updated-index-page&amp;quot;&amp;gt;
```jsx showLineNumbers
// resources/js/pages/Products/Index.tsx
import InputError from &amp;#39;@/components/input-error&amp;#39;;
import Product, { ProductProps } from &amp;#39;@/components/Product&amp;#39;;
import { Button } from &amp;#39;@/components/ui/button&amp;#39;;
import { Input } from &amp;#39;@/components/ui/input&amp;#39;;
import AppLayout from &amp;#39;@/layouts/app-layout&amp;#39;;
import { Head, useForm } from &amp;#39;@inertiajs/react&amp;#39;;
import { FormEventHandler } from &amp;#39;react&amp;#39;;

export default function Index({ products }: { products: ProductProps[] }) {
    const { data, setData, post, processing, reset, errors } = useForm({
        name: &amp;#39;&amp;#39;,
    });

    const submit: FormEventHandler = (e) =&amp;gt; {
        e.preventDefault();
        post(route(&amp;#39;products.store&amp;#39;), { onSuccess: () =&amp;gt; reset() });
    };

    return (
        &amp;lt;AppLayout&amp;gt;
            &amp;lt;Head title=&amp;quot;Products&amp;quot; /&amp;gt;

            &amp;lt;div className=&amp;quot;mx-auto max-w-2xl p-4 sm:p-6 lg:p-8&amp;quot;&amp;gt;
                &amp;lt;form onSubmit={submit}&amp;gt;
                    &amp;lt;Input value={data.name} placeholder=&amp;quot;Name of the product&amp;quot; onChange={(e) =&amp;gt; setData(&amp;#39;name&amp;#39;, e.target.value)} /&amp;gt;
                    &amp;lt;InputError message={errors.name} className=&amp;quot;mt-2&amp;quot; /&amp;gt;
                    &amp;lt;Button className=&amp;quot;mt-4&amp;quot; disabled={processing}&amp;gt;
                        Create
                    &amp;lt;/Button&amp;gt;
                &amp;lt;/form&amp;gt;
            &amp;lt;/div&amp;gt;
            &amp;lt;div className=&amp;quot;mt-6 divide-y rounded-lg bg-white shadow-sm&amp;quot;&amp;gt;
                {products.map((product) =&amp;gt; (
                    &amp;lt;Product key={product.id} {...product} /&amp;gt;
                ))}
            &amp;lt;/div&amp;gt;
        &amp;lt;/AppLayout&amp;gt;
    );
}
&lt;/code&gt;&lt;/pre&gt;


&lt;h1&gt;N+1 Query Problems and Solutions&lt;/h1&gt;
&lt;p&gt;One of the most common performance issues in Laravel applications is the N+1 query problem. Let&amp;#39;s understand what it is and how to solve it.&lt;/p&gt;
&lt;h2&gt;Understanding the N+1 Problem&lt;/h2&gt;

```php showLineNumbers
class ProductController extends Controller
{
/**
    * Display a listing of the resource.
    */
public function index()
{
    $products = Product::latest()-&gt;get();

&lt;pre&gt;&lt;code&gt;// This will trigger N+1 queries when we access user relationship
// For each product, Laravel will make a separate query to fetch the user
// If you have 100 products, it will make 1 query for products + 100 queries for users = 101 queries
$products-&amp;gt;each(function ($product) {
    $product-&amp;gt;user;
});

return Inertia::render(&amp;#39;Products/Index&amp;#39;, [
    &amp;#39;products&amp;#39; =&amp;gt; $products,
]);

// With eager loading
// This makes only 2 queries: 1 for products + 1 for all related users
// return Inertia::render(&amp;#39;Products/Index&amp;#39;, [
//     &amp;#39;products&amp;#39; =&amp;gt; Product::with(&amp;#39;user:id,name&amp;#39;)-&amp;gt;latest()-&amp;gt;get(),
// ]);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;}&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;/CodeBlock&amp;gt;

## Preventing Lazy Loading in Development

Add this to your AppServiceProvider to detect N+1 problems during development:

&amp;lt;CodeBlock title=&amp;quot;prevent-lazy-loading&amp;quot;&amp;gt;
```php showLineNumbers
# app/Providers/AppServiceProvider.php
public function boot(): void
{
    // Detect N+1 query problems in development
    // This will throw an exception when lazy loading occurs
    if (app()-&amp;gt;environment(&amp;#39;local&amp;#39;)) {
        Model::preventLazyLoading();
    }
}
&lt;/code&gt;&lt;/pre&gt;


&lt;h2&gt;Improving Date Display&lt;/h2&gt;
&lt;p&gt;Let&amp;#39;s install and use dayjs for better date formatting:&lt;/p&gt;

```bash showLineNumbers
npm install dayjs
```

---

```jsx showLineNumbers
// resources/js/components/Product.tsx
import dayjs from &apos;dayjs&apos;;
import relativeTime from &apos;dayjs/plugin/relativeTime&apos;;

&lt;p&gt;dayjs.extend(relativeTime);&lt;/p&gt;
&lt;p&gt;...
&lt;small className=&quot;ml-2 text-sm text-gray-600&quot;&gt;{dayjs(product.created_at).fromNow()}&lt;/small&gt;
...&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;/CodeBlock&amp;gt;

## Filtering User-Specific Products

You can also filter products to show only those belonging to the authenticated user:

&amp;lt;CodeBlock title=&amp;quot;user-specific-products&amp;quot;&amp;gt;
```php showLineNumbers
# get only user products
class ProductController extends Controller
{
    public function index()
    {
        return Inertia::render(&amp;#39;Products/Index&amp;#39;, [
            &amp;#39;products&amp;#39; =&amp;gt; Auth::user()-&amp;gt;products()-&amp;gt;with(&amp;#39;user:id,name&amp;#39;)-&amp;gt;latest()-&amp;gt;get(),
        ]);
    }
}
&lt;/code&gt;&lt;/pre&gt;


&lt;h1&gt;Editing Products&lt;/h1&gt;
&lt;p&gt;Now let&amp;#39;s implement the ability to edit products with proper authorization to ensure users can only edit their own products.&lt;/p&gt;
&lt;h2&gt;Adding Update Route&lt;/h2&gt;
&lt;p&gt;First, let&amp;#39;s add the update route to our resource routes:&lt;/p&gt;

```php showLineNumbers {4}
&lt;?php
 ...
Route::resource(&apos;products&apos;, ProductController::class)
    -&gt;only([&apos;index&apos;, &apos;store&apos;, &apos;update&apos;])
    -&gt;middleware([&apos;auth&apos;, &apos;verified&apos;]);
 ...
```


&lt;h2&gt;Enhanced Product Component with Editing&lt;/h2&gt;
&lt;p&gt;Let&amp;#39;s update our Product component to include editing functionality:&lt;/p&gt;

```jsx showLineNumbers
// resources/js/components/Product.tsx
import React, { useState } from &apos;react&apos;;
import dayjs from &apos;dayjs&apos;;
import relativeTime from &apos;dayjs/plugin/relativeTime&apos;;
import { MoreHorizontal, User } from &apos;lucide-react&apos;;
import { useForm, usePage } from &apos;@inertiajs/react&apos;;

&lt;p&gt;import InputError from &amp;#39;@/components/input-error&amp;#39;;
import { Button } from &amp;#39;@/components/ui/button&amp;#39;;
import {
   DropdownMenu,
   DropdownMenuContent,
   DropdownMenuItem,
   DropdownMenuTrigger
} from &amp;#39;@/components/ui/dropdown-menu&amp;#39;;
import { Input } from &amp;#39;@/components/ui/input&amp;#39;;
import { type SharedData } from &amp;#39;@/types&amp;#39;;&lt;/p&gt;
&lt;p&gt;dayjs.extend(relativeTime);&lt;/p&gt;
&lt;p&gt;export interface ProductProps {
   id: number;
   name: string;
   user: {
       id: number;
       name: string;
   };
   created_at: string;
   updated_at: string;
}&lt;/p&gt;
&lt;p&gt;export default function Product(product: ProductProps) {
   const { auth } = usePage().props;
   const [editing, setEditing] = useState(false);&lt;/p&gt;
&lt;p&gt;   const { data, setData, patch, clearErrors, reset, errors } = useForm({
       name: product.name,
   });&lt;/p&gt;
&lt;p&gt;   const submit = (e: React.FormEvent) =&amp;gt; {
       e.preventDefault();
       patch(route(&amp;#39;products.update&amp;#39;, product.id), {
           onSuccess: () =&amp;gt; setEditing(false)
       });
   };&lt;/p&gt;
&lt;p&gt;   return (
       &lt;div className=&quot;flex space-x-2 p-6&quot;&gt;
           
           &lt;div className=&quot;flex-1&quot;&gt;
               &lt;div className=&quot;flex items-center justify-between&quot;&gt;
                   &lt;div&gt;
                       &lt;span className=&quot;text-gray-800&quot;&gt;{product.user.name}&lt;/span&gt;
                       &lt;small className=&quot;ml-2 text-sm text-gray-600&quot;&gt;{dayjs(product.created_at).fromNow()}&lt;/small&gt;
                       {product.created_at !== product.updated_at &amp;amp;&amp;amp; (
                           &lt;small className=&quot;text-sm text-gray-600&quot;&gt; &amp;middot; edited&lt;/small&gt;
                       )}
                   &lt;/div&gt;
                   {product.user.id === auth.user.id &amp;amp;&amp;amp; (
                       
                           
                               
                                   
                               
                           
                           
                               &amp;lt;DropdownMenuItem onClick={() =&amp;gt; setEditing(true)}&amp;gt;
                                   Edit
                               
                           
                       
                   )}
               &lt;/div&gt;
               {editing ? (
                   &lt;form onSubmit={submit}&gt;
                       &amp;lt;Input
                           value={data.name}
                           onChange={e =&amp;gt; setData(&amp;#39;name&amp;#39;, e.target.value)}
                           className=&amp;quot;mt-4&amp;quot;
                       /&amp;gt;
                       
                       &lt;div className=&quot;space-x-2&quot;&gt;
                           Save
                           &amp;lt;Button
                               type=&amp;quot;button&amp;quot;
                               variant=&amp;quot;ghost&amp;quot;
                               className=&amp;quot;mt-4&amp;quot;
                               onClick={() =&amp;gt; {
                                   setEditing(false);
                                   reset();
                                   clearErrors();
                               }}
                           &amp;gt;
                               Cancel
                           
                       &lt;/div&gt;
                   &lt;/form&gt;
               ) : (
                   &lt;p className=&quot;mt-4 text-lg text-gray-900&quot;&gt;{product.name}&lt;/p&gt;
               )}
           &lt;/div&gt;
       &lt;/div&gt;
   );
}&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;/CodeBlock&amp;gt;

## Implementing the Update Controller Method

Now let&amp;#39;s implement the update method in our ProductController:

&amp;lt;CodeBlock title=&amp;quot;update-controller-method&amp;quot;&amp;gt;
```php showLineNumbers
&amp;lt;?php
class ProductController extends Controller
{
/**
 * Update the specified resource in storage.
 */
    public function update(Request $request, Product $product): RedirectResponse
    {
        Gate::authorize(&amp;#39;update&amp;#39;, $product);
        // if ($product-&amp;gt;user_id !== $request-&amp;gt;user()-&amp;gt;id) {
        //     abort(403, &amp;#39;Unauthorized action.&amp;#39;);
        // }

        $validated = $request-&amp;gt;validate([
            &amp;#39;name&amp;#39; =&amp;gt; &amp;#39;required|string|max:255&amp;#39;,
        ]);

        $product-&amp;gt;update($validated);

        return redirect(route(&amp;#39;products.index&amp;#39;));
    }
}
&lt;/code&gt;&lt;/pre&gt;


&lt;h2&gt;Authorization with Policies&lt;/h2&gt;
&lt;p&gt;For proper authorization, let&amp;#39;s create a policy to control who can update products:&lt;/p&gt;

```bash showLineNumbers
php artisan make:policy ProductPolicy --model=Product
```



```php showLineNumbers
# app/Policies/ProductPolicy.php
class ProductPolicy
{
    /**
     * Determine whether the user can update the model.
    */
    public function update(User $user, Product $product): bool
    {
        return $product-&gt;user_id === $user-&gt;id;
        // return $product-&gt;user()-&gt;is($user);
    }
}
```


&lt;h2&gt;Security Testing Example&lt;/h2&gt;

Here&apos;s an example of how you can test authorization without proper Gate protection. This demonstrates why authorization is crucial.


&lt;p&gt;&lt;strong&gt;Steps to test:&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Open Network Tab in browser&lt;/li&gt;
&lt;li&gt;Edit a product that the user owns&lt;/li&gt;
&lt;li&gt;Copy the X-XSRF-TOKEN from Request Headers&lt;/li&gt;
&lt;li&gt;Run this console command:&lt;/li&gt;
&lt;/ol&gt;

```javascript showLineNumbers
fetch(&apos;/products/11&apos;, {
    // Change to a product ID you don&apos;t own
    method: &apos;PATCH&apos;,
    headers: {
        &apos;Content-Type&apos;: &apos;application/json&apos;,
        &apos;X-XSRF-TOKEN&apos;:
            &apos;eyJpdiI6IjRFTy9Ma3Q0Ylc0NUlHRXJMRVcwUVE9PSIsInZhbHVlIjoiR1JoVHVpZithdlFqclArdHExcHdybC83VzJPVzRqbFd3eTJjRFZCUVJmNEhTUENvZXlISW1LTXBIZTdWRU9qaFBKL3VuTWFFOW1saFhYZDRBRnlsSzBBM2dEVGluckpjeUdCU0htZUpHd1FFUFVWT2hiL3JFV0U0anNodzJBZ1YiLCJtYWMiOiI1NjRkYTJhYmFiOWQyOTNmYjQzOGYzZTYyN2IzMjYxZDU0MTc0ZDZjYTcwMGRjMGM3M2JhZWZmODViYjlkNDA4IiwidGFnIjoiIn0=&apos;,
        &apos;X-Inertia&apos;: &apos;true&apos;,
        &apos;X-Requested-With&apos;: &apos;XMLHttpRequest&apos;,
    },
    body: JSON.stringify({
        name: &apos;HACKED PRODUCT!&apos;,
    }),
});
```


&lt;h1&gt;Deleting Products&lt;/h1&gt;
&lt;p&gt;Finally, let&amp;#39;s implement the delete functionality with proper authorization.&lt;/p&gt;
&lt;h2&gt;Adding Destroy Route&lt;/h2&gt;

```php showLineNumbers {2}
Route::resource(&apos;products&apos;, ProductController::class)
    -&gt;only([&apos;index&apos;, &apos;store&apos;, &apos;update&apos;, &apos;destroy&apos;])
    -&gt;middleware([&apos;auth&apos;, &apos;verified&apos;]);
```


&lt;h2&gt;Implementing the Destroy Method&lt;/h2&gt;

```php showLineNumbers {1, 3-5}
public function destroy(Product $product): RedirectResponse
{
    Gate::authorize(&apos;delete&apos;, $product);
    $product-&gt;delete();
    return redirect(route(&apos;products.index&apos;));
}
```


&lt;h2&gt;Adding Delete Policy&lt;/h2&gt;

```php showLineNumbers
public function delete(User $user, Product $product): bool
{
    return $this-&gt;update($user, $product);
}
```


&lt;h2&gt;Adding Delete Button to Component&lt;/h2&gt;

```jsx showLineNumbers {2-4, 7}
// resources/js/components/Product.tsx
const { data, setData, patch, clearErrors, reset, errors, delete: destroy } = useForm({
    name: product.name,
});

&lt;p&gt;...
&amp;lt;DropdownMenuItem onClick={() =&amp;gt; destroy(route(&amp;#39;products.destroy&amp;#39;, product.id))}&amp;gt;Delete&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;/CodeBlock&amp;gt;

## Conclusion

You now have a complete Laravel + Inertia.js + React application with:

- ✅ Product creation with validation
- ✅ Product listing with relationships
- ✅ Product editing with authorization
- ✅ Product deletion with security
- ✅ N+1 query optimization
- ✅ Proper database relationships
- ✅ User authentication and authorization

This foundation provides you with all the essential patterns for building modern web applications using this powerful stack.

# Bonus: Laravel Factory and Seeder for Products

Laravel factories and seeders provide a powerful way to generate test data for your application. This is especially useful during development and testing phases.

## Creating Product Factory

Generate a factory for the Product model:

&amp;lt;CodeBlock title=&amp;quot;create-factory&amp;quot;&amp;gt;
```bash showLineNumbers
php artisan make:factory ProductFactory
&lt;/code&gt;&lt;/pre&gt;



Make sure your Product model uses the `HasFactory` trait to enable factory functionality.



```php showLineNumbers {5, 11}
&lt;?php

&lt;p&gt;namespace App\Models;&lt;/p&gt;
&lt;p&gt;use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;&lt;/p&gt;
&lt;p&gt;class Product extends Model
{
    use HasFactory;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;protected $fillable = [&amp;#39;name&amp;#39;];

public function user(): BelongsTo
{
    return $this-&amp;gt;belongsTo(User::class);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;}&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;/CodeBlock&amp;gt;

Update the ProductFactory to define how fake products should be generated:

&amp;lt;CodeBlock title=&amp;quot;database/factories/ProductFactory.php&amp;quot;&amp;gt;
```php showLineNumbers {13-14}
&amp;lt;?php

namespace Database\Factories;

use App\Models\User;
use Illuminate\Database\Eloquent\Factories\Factory;

class ProductFactory extends Factory
{
    public function definition(): array
    {
        return [
            &amp;#39;user_id&amp;#39; =&amp;gt; User::inRandomOrder()-&amp;gt;first()?-&amp;gt;id ?? User::factory(),
            &amp;#39;name&amp;#39; =&amp;gt; fake()-&amp;gt;words(3, true),
        ];
    }
}
&lt;/code&gt;&lt;/pre&gt;


&lt;h2&gt;Creating Product Seeder&lt;/h2&gt;
&lt;p&gt;Generate a seeder to populate your database with sample products:&lt;/p&gt;

```bash showLineNumbers
php artisan make:seeder ProductSeeder
```


&lt;p&gt;Update the ProductSeeder:&lt;/p&gt;

```php showLineNumbers {12}
&lt;?php

&lt;p&gt;namespace Database\Seeders;&lt;/p&gt;
&lt;p&gt;use App\Models\Product;
use Illuminate\Database\Seeder;&lt;/p&gt;
&lt;p&gt;class ProductSeeder extends Seeder
{
    public function run(): void
    {
        Product::factory(50)-&amp;gt;create();
    }
}&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;/CodeBlock&amp;gt;

## Running Seeders

Add the ProductSeeder to your DatabaseSeeder:

&amp;lt;CodeBlock title=&amp;quot;database/seeders/DatabaseSeeder.php&amp;quot;&amp;gt;
```php showLineNumbers {11-13}
&amp;lt;?php

namespace Database\Seeders;

use Illuminate\Database\Seeder;

class DatabaseSeeder extends Seeder
{
    public function run(): void
    {
        $this-&amp;gt;call([
            ProductSeeder::class,
        ]);
    }
}
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;Run the seeders to populate your database:&lt;/p&gt;

```bash showLineNumbers
# Run all seeders
php artisan db:seed

&lt;h1&gt;Run specific seeder&lt;/h1&gt;
&lt;p&gt;php artisan db:seed --class=ProductSeeder&lt;/p&gt;
&lt;h1&gt;Fresh migration with seeding&lt;/h1&gt;
&lt;p&gt;php artisan migrate:fresh --seed&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;/CodeBlock&amp;gt;

## Using Factories in Tinker

You can also use factories directly in Tinker for quick testing:

&amp;lt;CodeBlock title=&amp;quot;tinker-factories&amp;quot;&amp;gt;
```bash showLineNumbers
php artisan tinker

# Create a single product
Product::factory()-&amp;gt;create();

# Create 5 products
Product::factory()-&amp;gt;count(5)-&amp;gt;create();

# Create products for a specific user
Product::factory()-&amp;gt;count(3)-&amp;gt;create([&amp;#39;user_id&amp;#39; =&amp;gt; 1]);
&lt;/code&gt;&lt;/pre&gt;



Factories and seeders are essential for maintaining consistent test data across different environments and team members.


&lt;h1&gt;Bonus: Laravel Middleware for Authorization&lt;/h1&gt;
&lt;p&gt;Laravel middleware provides a convenient mechanism for filtering HTTP requests entering your application. Instead of placing authorization logic directly in controllers, middleware offers a cleaner, more reusable approach.&lt;/p&gt;
&lt;h2&gt;Understanding Middleware&lt;/h2&gt;
&lt;p&gt;Middleware acts as a bridge between a request and a response. It&amp;#39;s like a series of layers that your request must pass through before reaching your application&amp;#39;s core logic. Each middleware can examine the request, modify it, or even terminate it entirely.&lt;/p&gt;
&lt;h2&gt;Creating Custom Middleware&lt;/h2&gt;
&lt;p&gt;Let&amp;#39;s create middleware to ensure users can only access their own products:&lt;/p&gt;

```bash showLineNumbers
php artisan make:middleware EnsureProductOwnership
```


&lt;p&gt;This creates a new middleware file at &lt;code&gt;app/Http/Middleware/EnsureProductOwnership.php&lt;/code&gt;:&lt;/p&gt;

```php showLineNumbers {16-22}
&lt;?php

&lt;p&gt;namespace App\Http\Middleware;&lt;/p&gt;
&lt;p&gt;use Closure;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;&lt;/p&gt;
&lt;p&gt;class EnsureProductOwnership
{
    /**
     * Handle an incoming request.
     */
    public function handle(Request $request, Closure $next): Response
    {
        $product = $request-&amp;gt;route(&amp;#39;product&amp;#39;);&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    if ($product &amp;amp;&amp;amp; $product-&amp;gt;user_id !== auth()-&amp;gt;id()) {
        abort(403, &amp;#39;Unauthorized access to product.&amp;#39;);
    }

    return $next($request);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;}&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;/CodeBlock&amp;gt;

## Registering Middleware in Laravel 12

In Laravel 12, middleware registration has been simplified. Register your middleware in `bootstrap/app.php`:

&amp;lt;CodeBlock title=&amp;quot;bootstrap/app.php&amp;quot;&amp;gt;
```php showLineNumbers {9-11}
&amp;lt;?php

use Illuminate\Foundation\Application;
use Illuminate\Foundation\Configuration\Exceptions;
use Illuminate\Foundation\Configuration\Middleware;

return Application::configure(basePath: dirname(__DIR__))
    -&amp;gt;withMiddleware(function (Middleware $middleware) {
        $middleware-&amp;gt;alias([
            &amp;#39;product.owner&amp;#39; =&amp;gt; \App\Http\Middleware\EnsureProductOwnership::class,
        ]);
    })
    -&amp;gt;withExceptions(function (Exceptions $exceptions) {
        //
    })-&amp;gt;create();
&lt;/code&gt;&lt;/pre&gt;


&lt;h2&gt;Applying Middleware to Routes&lt;/h2&gt;
&lt;p&gt;Now you can apply the middleware to your routes in several ways:&lt;/p&gt;
&lt;h3&gt;Option 1: Individual Routes&lt;/h3&gt;

```php showLineNumbers {3-4}
Route::resource(&apos;products&apos;, ProductController::class)
    -&gt;only([&apos;index&apos;, &apos;store&apos;, &apos;update&apos;, &apos;destroy&apos;])
    -&gt;middleware([&apos;auth&apos;, &apos;verified&apos;]);

&lt;p&gt;Route::middleware(&amp;#39;product.owner&amp;#39;)-&amp;gt;group(function () {
    Route::patch(&amp;#39;/products/{product}&amp;#39;, [ProductController::class, &amp;#39;update&amp;#39;])-&amp;gt;name(&amp;#39;products.update&amp;#39;);
    Route::delete(&amp;#39;/products/{product}&amp;#39;, [ProductController::class, &amp;#39;destroy&amp;#39;])-&amp;gt;name(&amp;#39;products.destroy&amp;#39;);
});&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;/CodeBlock&amp;gt;

### Option 2: Route Groups

&amp;lt;CodeBlock title=&amp;quot;routes/web.php&amp;quot;&amp;gt;
```php showLineNumbers
Route::middleware([&amp;#39;auth&amp;#39;, &amp;#39;verified&amp;#39;])-&amp;gt;group(function () {
    Route::get(&amp;#39;/products&amp;#39;, [ProductController::class, &amp;#39;index&amp;#39;])-&amp;gt;name(&amp;#39;products.index&amp;#39;);
    Route::post(&amp;#39;/products&amp;#39;, [ProductController::class, &amp;#39;store&amp;#39;])-&amp;gt;name(&amp;#39;products.store&amp;#39;);

    Route::middleware(&amp;#39;product.owner&amp;#39;)-&amp;gt;group(function () {
        Route::patch(&amp;#39;/products/{product}&amp;#39;, [ProductController::class, &amp;#39;update&amp;#39;])-&amp;gt;name(&amp;#39;products.update&amp;#39;);
        Route::delete(&amp;#39;/products/{product}&amp;#39;, [ProductController::class, &amp;#39;destroy&amp;#39;])-&amp;gt;name(&amp;#39;products.destroy&amp;#39;);
    });
});
&lt;/code&gt;&lt;/pre&gt;


&lt;h3&gt;Option 3: Controller Constructor&lt;/h3&gt;

```php showLineNumbers {5-8}
&lt;?php

&lt;p&gt;class ProductController extends Controller
{
    public function __construct()
    {
        $this-&amp;gt;middleware(&amp;#39;product.owner&amp;#39;)-&amp;gt;only([&amp;#39;update&amp;#39;, &amp;#39;destroy&amp;#39;]);
    }&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// ... rest of controller methods
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;}&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;/CodeBlock&amp;gt;

## Simplifying Controller Methods

With middleware handling authorization, you can remove the authorization logic from your controller methods:

### Global Middleware

For middleware that should run on every request, add it to the global middleware stack:

&amp;lt;CodeBlock title=&amp;quot;global-middleware&amp;quot;&amp;gt;
```php showLineNumbers
// bootstrap/app.php
-&amp;gt;withMiddleware(function (Middleware $middleware) {
    $middleware-&amp;gt;append(\App\Http\Middleware\LogRequests::class);
})
&lt;/code&gt;&lt;/pre&gt;


&lt;h2&gt;Benefits of Middleware Approach&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Separation of Concerns&lt;/strong&gt;: Authorization logic is separated from business logic&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Reusability&lt;/strong&gt;: Same middleware can be applied to multiple routes&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Consistency&lt;/strong&gt;: Ensures authorization is always checked&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Security&lt;/strong&gt;: Harder to forget authorization checks&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Maintainability&lt;/strong&gt;: Centralized authorization logic&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Performance&lt;/strong&gt;: Can terminate requests early without hitting controllers&lt;/li&gt;
&lt;/ol&gt;

Use middleware for cross-cutting concerns like authentication, authorization, logging, and rate limiting. Keep your controllers focused on business logic.


&lt;h1&gt;Bonus: Laravel Pail - Real-time Log Monitoring&lt;/h1&gt;
&lt;p&gt;Laravel Pail allows you to monitor your application&amp;#39;s logs in real-time directly from the console. It works with any log driver and provides filtering options.&lt;/p&gt;
&lt;h2&gt;Installation and Usage&lt;/h2&gt;

```bash showLineNumbers
# Install Laravel Pail
composer require laravel/pail

&lt;h1&gt;Basic usage&lt;/h1&gt;
&lt;p&gt;php artisan pail&lt;/p&gt;
&lt;h1&gt;Verbose output (avoid truncation)&lt;/h1&gt;
&lt;p&gt;php artisan pail -v&lt;/p&gt;
&lt;h1&gt;Maximum verbosity with stack traces&lt;/h1&gt;
&lt;p&gt;php artisan pail -vv&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;/CodeBlock&amp;gt;

## Example with Logging

Add logging to your ProductController:

&amp;lt;CodeBlock title=&amp;quot;ProductController.php&amp;quot;&amp;gt;
```php showLineNumbers {5-9}
public function index(): Response
{
    $products = Product::with(&amp;#39;user:id,name&amp;#39;)-&amp;gt;latest()-&amp;gt;get();

    Log::info(&amp;#39;Products index accessed&amp;#39;, [
        &amp;#39;user_id&amp;#39; =&amp;gt; auth()-&amp;gt;id(),
        &amp;#39;products_count&amp;#39; =&amp;gt; $products-&amp;gt;count(),
        &amp;#39;products&amp;#39; =&amp;gt; $products-&amp;gt;toArray()
    ]);

    return Inertia::render(&amp;#39;Products/Index&amp;#39;, [
        &amp;#39;products&amp;#39; =&amp;gt; $products,
    ]);
}
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;Now monitor your logs in real-time:&lt;/p&gt;

```bash showLineNumbers
# Monitor all logs with verbose output
php artisan pail -v

&lt;h1&gt;Filter by specific content&lt;/h1&gt;
&lt;p&gt;php artisan pail --filter=&amp;quot;Products index accessed&amp;quot;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;/CodeBlock&amp;gt;

---

# Shadcn Tanstack DataTable:

&amp;lt;CodeBlock title=&amp;quot;shadcn datatable&amp;quot;&amp;gt;
```jsx showLineNumbers
// resources/js/components/Product.tsx
import { router, useForm, usePage } from &amp;#39;@inertiajs/react&amp;#39;;
import {
    ColumnDef,
    ColumnFiltersState,
    flexRender,
    getCoreRowModel,
    getFilteredRowModel,
    getPaginationRowModel,
    getSortedRowModel,
    SortingState,
    useReactTable,
} from &amp;#39;@tanstack/react-table&amp;#39;;
import dayjs from &amp;#39;dayjs&amp;#39;;
import relativeTime from &amp;#39;dayjs/plugin/relativeTime&amp;#39;;
import { ArrowUpDown, ChevronLeft, ChevronRight, Edit, Search, Trash2, X, Check } from &amp;#39;lucide-react&amp;#39;;
import { useState } from &amp;#39;react&amp;#39;;

import InputError from &amp;#39;@/components/input-error&amp;#39;;
import { Button } from &amp;#39;@/components/ui/button&amp;#39;;
import { Input } from &amp;#39;@/components/ui/input&amp;#39;;
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from &amp;#39;@/components/ui/table&amp;#39;;
import { type SharedData } from &amp;#39;@/types&amp;#39;;

dayjs.extend(relativeTime);

export interface ProductProps {
    id: number;
    name: string;
    user: {
        id: number;
        name: string;
    };
    created_at: string;
    updated_at: string;
}

interface ProductsTableProps {
    products: ProductProps[];
}

export default function ProductsTable({ products }: ProductsTableProps) {
    const { auth } = usePage&amp;lt;SharedData&amp;gt;().props;
    const [sorting, setSorting] = useState&amp;lt;SortingState&amp;gt;([]);
    const [columnFilters, setColumnFilters] = useState&amp;lt;ColumnFiltersState&amp;gt;([]);
    const [globalFilter, setGlobalFilter] = useState(&amp;#39;&amp;#39;);
    const [editingId, setEditingId] = useState&amp;lt;number | null&amp;gt;(null);

    // Form for editing
    const { data, setData, patch, clearErrors, reset, errors } = useForm({
        name: &amp;#39;&amp;#39;,
    });

    const startEdit = (product: ProductProps) =&amp;gt; {
        setEditingId(product.id);
        setData(&amp;#39;name&amp;#39;, product.name);
        clearErrors();
    };

    const saveEdit = (productId: number) =&amp;gt; {
        patch(route(&amp;#39;products.update&amp;#39;, productId), {
            onSuccess: () =&amp;gt; {
                setEditingId(null);
                reset();
            },
        });
    };

    const cancelEdit = () =&amp;gt; {
        setEditingId(null);
        reset();
        clearErrors();
    };

    const columns: ColumnDef&amp;lt;ProductProps&amp;gt;[] = [
        {
            accessorKey: &amp;quot;name&amp;quot;,
            header: ({ column }) =&amp;gt; {
                return (
                    &amp;lt;Button
                        variant=&amp;quot;ghost&amp;quot;
                        onClick={() =&amp;gt; column.toggleSorting(column.getIsSorted() === &amp;quot;asc&amp;quot;)}
                        className=&amp;quot;h-auto p-0 font-medium&amp;quot;
                    &amp;gt;
                        Product Name
                        &amp;lt;ArrowUpDown className=&amp;quot;ml-2 h-4 w-4&amp;quot; /&amp;gt;
                    &amp;lt;/Button&amp;gt;
                )
            },
            cell: ({ row }) =&amp;gt; {
                const product = row.original;
                const isEditing = editingId === product.id;

                if (isEditing) {
                    return (
                        &amp;lt;div className=&amp;quot;flex items-center space-x-2&amp;quot;&amp;gt;
                            &amp;lt;Input
                                value={data.name}
                                onChange={(e) =&amp;gt; setData(&amp;#39;name&amp;#39;, e.target.value)}
                                className=&amp;quot;h-8&amp;quot;
                                autoFocus
                            /&amp;gt;
                            {errors.name &amp;amp;&amp;amp; (
                                &amp;lt;InputError message={errors.name} className=&amp;quot;mt-1&amp;quot; /&amp;gt;
                            )}
                        &amp;lt;/div&amp;gt;
                    );
                }

                return &amp;lt;div className=&amp;quot;font-medium max-w-xs truncate&amp;quot;&amp;gt;{row.getValue(&amp;quot;name&amp;quot;)}&amp;lt;/div&amp;gt;;
            },
            size: 300,
        },
        {
            accessorKey: &amp;quot;user.name&amp;quot;,
            header: &amp;quot;Created By&amp;quot;,
            cell: ({ row }) =&amp;gt; &amp;lt;div className=&amp;quot;text-sm&amp;quot;&amp;gt;{row.original.user.name}&amp;lt;/div&amp;gt;,
            size: 150,
        },
        {
            accessorKey: &amp;quot;created_at&amp;quot;,
            header: ({ column }) =&amp;gt; {
                return (
                    &amp;lt;Button
                        variant=&amp;quot;ghost&amp;quot;
                        onClick={() =&amp;gt; column.toggleSorting(column.getIsSorted() === &amp;quot;asc&amp;quot;)}
                        className=&amp;quot;h-auto p-0 font-medium&amp;quot;
                    &amp;gt;
                        Created
                        &amp;lt;ArrowUpDown className=&amp;quot;ml-2 h-4 w-4&amp;quot; /&amp;gt;
                    &amp;lt;/Button&amp;gt;
                )
            },
            cell: ({ row }) =&amp;gt; {
                const date = row.getValue(&amp;quot;created_at&amp;quot;) as string;
                return &amp;lt;div className=&amp;quot;text-sm text-muted-foreground&amp;quot;&amp;gt;{dayjs(date).fromNow()}&amp;lt;/div&amp;gt;;
            },
            size: 120,
        },
        {
            id: &amp;quot;actions&amp;quot;,
            header: &amp;quot;Actions&amp;quot;,
            enableHiding: false,
            cell: ({ row }) =&amp;gt; {
                const product = row.original;
                const canEdit = product.user.id === auth.user.id;
                const isEditing = editingId === product.id;

                if (!canEdit) return &amp;lt;div className=&amp;quot;w-32&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;;

                if (isEditing) {
                    return (
                        &amp;lt;div className=&amp;quot;flex space-x-2&amp;quot;&amp;gt;
                            &amp;lt;Button
                                variant=&amp;quot;outline&amp;quot;
                                size=&amp;quot;sm&amp;quot;
                                onClick={() =&amp;gt; saveEdit(product.id)}
                            &amp;gt;
                                &amp;lt;Check className=&amp;quot;h-4 w-4 mr-1&amp;quot; /&amp;gt;
                                Save
                            &amp;lt;/Button&amp;gt;
                            &amp;lt;Button
                                variant=&amp;quot;ghost&amp;quot;
                                size=&amp;quot;sm&amp;quot;
                                onClick={cancelEdit}
                            &amp;gt;
                                &amp;lt;X className=&amp;quot;h-4 w-4 mr-1&amp;quot; /&amp;gt;
                                Cancel
                            &amp;lt;/Button&amp;gt;
                        &amp;lt;/div&amp;gt;
                    );
                }

                return (
                    &amp;lt;div className=&amp;quot;flex space-x-2&amp;quot;&amp;gt;
                        &amp;lt;Button
                            variant=&amp;quot;outline&amp;quot;
                            size=&amp;quot;sm&amp;quot;
                            onClick={() =&amp;gt; startEdit(product)}
                        &amp;gt;
                            &amp;lt;Edit className=&amp;quot;h-4 w-4 mr-1&amp;quot; /&amp;gt;
                            Edit
                        &amp;lt;/Button&amp;gt;
                        &amp;lt;Button
                            variant=&amp;quot;destructive&amp;quot;
                            size=&amp;quot;sm&amp;quot;
                            onClick={() =&amp;gt; {
                                if (confirm(&amp;#39;Are you sure you want to delete this product?&amp;#39;)) {
                                    router.delete(route(&amp;#39;products.destroy&amp;#39;, product.id));
                                }
                            }}
                        &amp;gt;
                            &amp;lt;Trash2 className=&amp;quot;h-4 w-4 mr-1&amp;quot; /&amp;gt;
                            Delete
                        &amp;lt;/Button&amp;gt;
                    &amp;lt;/div&amp;gt;
                );
            },
            size: 200,
        },
    ];

    const table = useReactTable({
        data: products,
        columns,
        onSortingChange: setSorting,
        onColumnFiltersChange: setColumnFilters,
        getCoreRowModel: getCoreRowModel(),
        getPaginationRowModel: getPaginationRowModel(),
        getSortedRowModel: getSortedRowModel(),
        getFilteredRowModel: getFilteredRowModel(),
        onGlobalFilterChange: setGlobalFilter,
        globalFilterFn: &amp;#39;includesString&amp;#39;,
        state: {
            sorting,
            columnFilters,
            globalFilter,
        },
    });

    return (
        &amp;lt;div className=&amp;quot;w-full&amp;quot;&amp;gt;
            {/* Search Input */}
            &amp;lt;div className=&amp;quot;flex items-center py-4&amp;quot;&amp;gt;
                &amp;lt;div className=&amp;quot;relative max-w-sm&amp;quot;&amp;gt;
                    &amp;lt;Search className=&amp;quot;absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground&amp;quot; /&amp;gt;
                    &amp;lt;Input
                        placeholder=&amp;quot;Search products...&amp;quot;
                        value={globalFilter ?? &amp;#39;&amp;#39;}
                        onChange={(event) =&amp;gt; setGlobalFilter(String(event.target.value))}
                        className=&amp;quot;pl-10&amp;quot;
                    /&amp;gt;
                &amp;lt;/div&amp;gt;
            &amp;lt;/div&amp;gt;

            &amp;lt;div className=&amp;quot;rounded-md border bg-white shadow-sm&amp;quot;&amp;gt;
                &amp;lt;Table&amp;gt;
                    &amp;lt;TableHeader&amp;gt;
                        {table.getHeaderGroups().map((headerGroup) =&amp;gt; (
                            &amp;lt;TableRow key={headerGroup.id} className=&amp;quot;border-b&amp;quot;&amp;gt;
                                {headerGroup.headers.map((header, index) =&amp;gt; {
                                    let className = &amp;quot;text-left font-medium&amp;quot;;

                                    // Set specific widths for each column
                                    if (index === 0) className += &amp;quot; w-2/5&amp;quot;; // Product Name - 40%
                                    else if (index === 1) className += &amp;quot; w-1/5&amp;quot;; // Created By - 20%
                                    else if (index === 2) className += &amp;quot; w-1/5&amp;quot;; // Created - 20%
                                    else if (index === 3) className += &amp;quot; w-1/5&amp;quot;; // Actions - 20%

                                    return (
                                        &amp;lt;TableHead key={header.id} className={className}&amp;gt;
                                            {header.isPlaceholder
                                                ? null
                                                : flexRender(
                                                    header.column.columnDef.header,
                                                    header.getContext()
                                                )}
                                        &amp;lt;/TableHead&amp;gt;
                                    )
                                })}
                            &amp;lt;/TableRow&amp;gt;
                        ))}
                    &amp;lt;/TableHeader&amp;gt;
                    &amp;lt;TableBody&amp;gt;
                        {table.getRowModel().rows?.length ? (
                            table.getRowModel().rows.map((row) =&amp;gt; (
                                &amp;lt;TableRow
                                    key={row.id}
                                    data-state={row.getIsSelected() &amp;amp;&amp;amp; &amp;quot;selected&amp;quot;}
                                    className=&amp;quot;border-b hover:bg-gray-50&amp;quot;
                                &amp;gt;
                                    {row.getVisibleCells().map((cell, index) =&amp;gt; {
                                        let className = &amp;quot;py-3&amp;quot;;

                                        // Set specific widths for each column
                                        if (index === 0) className += &amp;quot; w-2/5&amp;quot;; // Product Name
                                        else if (index === 1) className += &amp;quot; w-1/5&amp;quot;; // Created By
                                        else if (index === 2) className += &amp;quot; w-1/5&amp;quot;; // Created
                                        else if (index === 3) className += &amp;quot; w-1/5&amp;quot;; // Actions

                                        return (
                                            &amp;lt;TableCell key={cell.id} className={className}&amp;gt;
                                                {flexRender(
                                                    cell.column.columnDef.cell,
                                                    cell.getContext()
                                                )}
                                            &amp;lt;/TableCell&amp;gt;
                                        )
                                    })}
                                &amp;lt;/TableRow&amp;gt;
                            ))
                        ) : (
                            &amp;lt;TableRow&amp;gt;
                                &amp;lt;TableCell
                                    colSpan={columns.length}
                                    className=&amp;quot;h-24 text-center text-muted-foreground&amp;quot;
                                &amp;gt;
                                    No products found.
                                &amp;lt;/TableCell&amp;gt;
                            &amp;lt;/TableRow&amp;gt;
                        )}
                    &amp;lt;/TableBody&amp;gt;
                &amp;lt;/Table&amp;gt;
            &amp;lt;/div&amp;gt;

            {/* Pagination Controls */}
            &amp;lt;div className=&amp;quot;flex items-center justify-between space-x-2 py-4&amp;quot;&amp;gt;
                &amp;lt;div className=&amp;quot;text-sm text-muted-foreground&amp;quot;&amp;gt;
                    {table.getFilteredSelectedRowModel().rows.length} of{&amp;quot; &amp;quot;}
                    {table.getFilteredRowModel().rows.length} row(s) selected.
                &amp;lt;/div&amp;gt;
                &amp;lt;div className=&amp;quot;flex items-center space-x-2&amp;quot;&amp;gt;
                    &amp;lt;p className=&amp;quot;text-sm font-medium&amp;quot;&amp;gt;
                        Page {table.getState().pagination.pageIndex + 1} of{&amp;quot; &amp;quot;}
                        {table.getPageCount()}
                    &amp;lt;/p&amp;gt;
                    &amp;lt;div className=&amp;quot;flex items-center space-x-2&amp;quot;&amp;gt;
                        &amp;lt;Button
                            variant=&amp;quot;outline&amp;quot;
                            size=&amp;quot;sm&amp;quot;
                            onClick={() =&amp;gt; table.previousPage()}
                            disabled={!table.getCanPreviousPage()}
                        &amp;gt;
                            &amp;lt;ChevronLeft className=&amp;quot;h-4 w-4&amp;quot; /&amp;gt;
                            Previous
                        &amp;lt;/Button&amp;gt;
                        &amp;lt;Button
                            variant=&amp;quot;outline&amp;quot;
                            size=&amp;quot;sm&amp;quot;
                            onClick={() =&amp;gt; table.nextPage()}
                            disabled={!table.getCanNextPage()}
                        &amp;gt;
                            Next
                            &amp;lt;ChevronRight className=&amp;quot;h-4 w-4&amp;quot; /&amp;gt;
                        &amp;lt;/Button&amp;gt;
                    &amp;lt;/div&amp;gt;
                &amp;lt;/div&amp;gt;
            &amp;lt;/div&amp;gt;
        &amp;lt;/div&amp;gt;
    );
}
&lt;/code&gt;&lt;/pre&gt;



```tsx ShowLineNumbers
// resources/js/pages/Products/Index.tsx
import InputError from &apos;@/components/input-error&apos;;
import ProductsTable, { ProductProps } from &apos;@/components/Product&apos;;
import { Button } from &apos;@/components/ui/button&apos;;
import { Input } from &apos;@/components/ui/input&apos;;
import AppLayout from &apos;@/layouts/app-layout&apos;;
import { Head, useForm } from &apos;@inertiajs/react&apos;;
import { FormEventHandler } from &apos;react&apos;;

&lt;p&gt;export default function Index({ products }: { products: ProductProps[] }) {
    const { data, setData, post, processing, reset, errors } = useForm({
        name: &amp;#39;&amp;#39;,
    });&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const submit: FormEventHandler = (e) =&amp;gt; {
    e.preventDefault();
    post(route(&amp;#39;products.store&amp;#39;), { onSuccess: () =&amp;gt; reset() });
};

return (
    &amp;lt;AppLayout&amp;gt;
        &amp;lt;Head title=&amp;quot;Products&amp;quot; /&amp;gt;

        &amp;lt;div className=&amp;quot;mx-auto max-w-2xl p-4 sm:p-6 lg:p-8&amp;quot;&amp;gt;
            &amp;lt;form onSubmit={submit} className=&amp;quot;flex items-center gap-4&amp;quot;&amp;gt;
                &amp;lt;Input value={data.name} placeholder=&amp;quot;Name of the product&amp;quot; onChange={(e) =&amp;gt; setData(&amp;#39;name&amp;#39;, e.target.value)} /&amp;gt;
                &amp;lt;Button disabled={processing}&amp;gt;Create&amp;lt;/Button&amp;gt;
            &amp;lt;/form&amp;gt;
            &amp;lt;InputError message={errors.name} className=&amp;quot;mt-2&amp;quot; /&amp;gt;
        &amp;lt;/div&amp;gt;
        &amp;lt;div className=&amp;quot;mx-auto mt-6 max-w-7xl px-4 sm:px-6 lg:px-8&amp;quot;&amp;gt;
            &amp;lt;ProductsTable products={products} /&amp;gt;
        &amp;lt;/div&amp;gt;
    &amp;lt;/AppLayout&amp;gt;
);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;}&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;/CodeBlock&amp;gt;
---
# Lravel Pagination

&amp;lt;CodeBlock title=&amp;quot;ProductController.php&amp;quot;&amp;gt;
```php showLineNumbers
public function index(Request $request)
{
    $perPage = $request-&amp;gt;get(&amp;#39;per_page&amp;#39;, 10); // Default 10 items per page

    $products = Product::with(&amp;#39;user:id,name&amp;#39;)
        -&amp;gt;latest()
        -&amp;gt;paginate($perPage);

    return Inertia::render(&amp;#39;Products/Index&amp;#39;, [
        &amp;#39;products&amp;#39; =&amp;gt; $products,
    ]);
}
&lt;/code&gt;&lt;/pre&gt;

---

```tsx showLineNumbers
// resources/js/types/index.d.ts
export interface PaginatedData {
    data: T[];
    current_page: number;
    first_page_url: string;
    from: number;
    last_page: number;
    last_page_url: string;
    links: PaginationLink[];
    next_page_url: string | null;
    path: string;
    per_page: number;
    prev_page_url: string | null;
    to: number;
    total: number;
}

&lt;p&gt;export interface PaginationLink {
    url: string | null;
    label: string;
    active: boolean;
}&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;/CodeBlock&amp;gt;
---
&amp;lt;CodeBlock title=&amp;quot;Product.tsx&amp;quot;&amp;gt;
```tsx showLineNumbers {2, 5, 9, 23, 24, 32, 36, 42, 43, 51, 52}
// resources/js/components/Paginat.tsx
import { type SharedData, type PaginatedData } from &amp;#39;@/types&amp;#39;;

interface ProductsTableProps {
    products: PaginatedData&amp;lt;ProductProps&amp;gt;;
}

const table = useReactTable({
    data: products.data,
    columns,
    onSortingChange: setSorting,
    onColumnFiltersChange: setColumnFilters,
    getCoreRowModel: getCoreRowModel(),
    getSortedRowModel: getSortedRowModel(),
    getFilteredRowModel: getFilteredRowModel(),
    onGlobalFilterChange: setGlobalFilter,
    globalFilterFn: &amp;#39;includesString&amp;#39;,
    state: {
        sorting,
        columnFilters,
        globalFilter,
    },
    manualPagination: true, // Tell TanStack Table we&amp;#39;re handling pagination manually
    pageCount: products.last_page,
});

...

{/* Server-Side Pagination Controls */}
&amp;lt;div className=&amp;quot;flex items-center justify-between space-x-2 py-4&amp;quot;&amp;gt;
    &amp;lt;div className=&amp;quot;text-sm text-muted-foreground&amp;quot;&amp;gt;
        Showing {products.from} to {products.to} of {products.total} results
    &amp;lt;/div&amp;gt;
    &amp;lt;div className=&amp;quot;flex items-center space-x-2&amp;quot;&amp;gt;
        &amp;lt;p className=&amp;quot;text-sm font-medium&amp;quot;&amp;gt;
            Page {products.current_page} of {products.last_page}
        &amp;lt;/p&amp;gt;
        &amp;lt;div className=&amp;quot;flex items-center space-x-2&amp;quot;&amp;gt;
            &amp;lt;Button
                variant=&amp;quot;outline&amp;quot;
                size=&amp;quot;sm&amp;quot;
                onClick={() =&amp;gt; router.get(products.prev_page_url || &amp;#39;&amp;#39;)}
                disabled={!products.prev_page_url}
            &amp;gt;
                &amp;lt;ChevronLeft className=&amp;quot;h-4 w-4&amp;quot; /&amp;gt;
                Previous
            &amp;lt;/Button&amp;gt;
            &amp;lt;Button
                variant=&amp;quot;outline&amp;quot;
                size=&amp;quot;sm&amp;quot;
                onClick={() =&amp;gt; router.get(products.next_page_url || &amp;#39;&amp;#39;)}
                disabled={!products.next_page_url}
            &amp;gt;
                Next
                &amp;lt;ChevronRight className=&amp;quot;h-4 w-4&amp;quot; /&amp;gt;
            &amp;lt;/Button&amp;gt;
        &amp;lt;/div&amp;gt;
    &amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
]]></content:encoded>
            <dc:creator>Rami Chabchoub</dc:creator>
        </item>
        <item>
            <title><![CDATA[Memoization with useMemo, useCallback and React.memo]]></title>
            <description><![CDATA[A guide to memoization in React, including useMemo, useCallback, and React.memo.]]></description>
            <link>https://www.ramicode.com/en/articles/memoization</link>
            <guid isPermaLink="false">memoization</guid>
            <dc:creator><![CDATA[Rami Chabchoub]]></dc:creator>
            <pubDate>Tue, 21 Jan 2025 00:00:00 GMT</pubDate>
            <content:encoded><![CDATA[&lt;p&gt;Now that we know the most important composition patterns and how they work, it&amp;#39;s time to talk about performance some more.
More precisely, let&amp;#39;s discuss the topic that is strongly associated with improving performance in React, but in reality, doesn&amp;#39;t work as we intend to at least half the time we&amp;#39;re doing it.
Memoization. Our favorite &lt;code&gt;useMemo&lt;/code&gt; and &lt;code&gt;useCallback&lt;/code&gt; hooks and the &lt;code&gt;React.memo&lt;/code&gt; higher-order component.
And I&amp;#39;m not joking or exaggerating about half the time by the way.
Doing memoization properly is hard, much harder than it seems.
By the end of this chapter, hopefully, you&amp;#39;ll agree with me.
Here you&amp;#39;ll learn:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;What is the problem we&amp;#39;re trying to solve with memoization (and it&amp;#39;s not performance per se!).&lt;/li&gt;
&lt;li&gt;How &lt;code&gt;useMemo&lt;/code&gt; and &lt;code&gt;useCallback&lt;/code&gt; work under the hood, and what is the difference between them.&lt;/li&gt;
&lt;li&gt;Why memoizing props on a component by itself is an anti-pattern.&lt;/li&gt;
&lt;li&gt;What &lt;code&gt;React.memo&lt;/code&gt; is, why we need it, and what are the basic rules for using it successfully.&lt;/li&gt;
&lt;li&gt;How to use it properly with the &amp;quot;elements as children&amp;quot; pattern.&lt;/li&gt;
&lt;li&gt;What is the role of &lt;code&gt;useMemo&lt;/code&gt; in expensive calculations.&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;The problem: comparing values&lt;/h1&gt;
&lt;p&gt;It&amp;#39;s all about comparing values in JavaScript.
Primitive values like strings or booleans we compare by their actual value:&lt;/p&gt;

```js
const a = 1;
const b = 1;
a === b; // will be true, values are exactly the same
```


&lt;p&gt;With objects and anything inherited from objects (like arrays or functions), it&amp;#39;s a different story.&lt;/p&gt;
&lt;p&gt;When we create a variable with an object &lt;code&gt;const a = { id: 1 }&lt;/code&gt;, the value stored there is not the actual value. It&amp;#39;s just a reference to some part of the memory that holds that object. When we create another variable with the same data &lt;code&gt;const b = { id: 1 }&lt;/code&gt;, it will be stored in another part of memory. And since it&amp;#39;s a different part, the reference to it will also be different.&lt;/p&gt;
&lt;p&gt;So even if these objects look exactly the same, the values in our fresh &lt;code&gt;a&lt;/code&gt; and &lt;code&gt;b&lt;/code&gt; variables are different: they point to different objects in memory. As a result, a simple comparison between them will always return false:&lt;/p&gt;

```js
const a = { id: 1 };
const b = { id: 1 };
a === b; // will always be false
```


&lt;p&gt;To make the comparison of &lt;code&gt;a === b&lt;/code&gt; return true , we need to make
sure that the reference in &lt;code&gt;b&lt;/code&gt; is exactly the same as the reference in &lt;code&gt;a&lt;/code&gt;.
Something like this:&lt;/p&gt;

```js
const a = { id: 1 };
const b = a;
a === b; // will be true
```


&lt;p&gt;This is what React has to deal with any time it needs to compare values
between re-renders. It does this comparison every time we use hooks
with dependencies, like in &lt;code&gt;useEffect&lt;/code&gt; for example:&lt;/p&gt;

```js
const Component = () =&gt; {
const submit = () =&gt; {};
useEffect(() =&gt; {
// call the function here
submit();
// it&apos;s declared outside of the useEffect
// so should be in the dependencies
}, [submit]);
return ...
}
```


&lt;p&gt;In this example, the &lt;code&gt;submit&lt;/code&gt; function is declared outside of the
useEffect hook. So if I want to use it inside the hook, it should be
declared as a dependency. But since &lt;code&gt;submit&lt;/code&gt; is declared locally inside
&lt;code&gt;Component&lt;/code&gt; , it will be re-created every time &lt;code&gt;Component&lt;/code&gt; re-renders.
Remember we discussed in Chapter 2. Elements, children as props, and
re-renders - a re-render is just React calling the component&amp;#39;s functions.
Every local variable during that will be re-created, exactly the same as
any function in JavaScript.
So React will compare &lt;code&gt;submit&lt;/code&gt; before and after re-render in order to
determine whether it should run the &lt;code&gt;useEffect&lt;/code&gt; hook this time. The
comparison will always return &lt;code&gt;false&lt;/code&gt; since it&amp;#39;s a new reference each
time. As a result, the &lt;code&gt;useEffect&lt;/code&gt; hook will be triggered on every re-
render.&lt;/p&gt;
&lt;h1&gt;useMemo and useCallback: how they work&lt;/h1&gt;
&lt;p&gt;In order to battle that, we need a way to preserve the reference to the
submit function between re-renders. So that the comparison returns
true and the hook is not triggered unnecessarily. This is where
useMemo and useCallback hooks come in. Both have a similar API
and serve a similar purpose: to make sure that the reference in the
variable those hooks are assigned to changes only when the dependency
of the hook changes.
If I wrap that &lt;code&gt;submit&lt;/code&gt; in &lt;code&gt;useCallback&lt;/code&gt; :&lt;/p&gt;

```js
const submit = useCallback(() =&gt; {
// no dependencies, reference won&apos;t change between re-renders
}, []);
}
```


&lt;p&gt;then the value in the &lt;code&gt;submit&lt;/code&gt; variable will be the same reference
between re-renders, the comparison will return &lt;code&gt;true&lt;/code&gt; , and the
&lt;code&gt;useEffect&lt;/code&gt; hook that depends on it won&amp;#39;t be triggered every time:&lt;/p&gt;

```js
const Component = () =&gt; {
const submit = useCallback(() =&gt; {
// submit something here
}, [])
useEffect(() =&gt; {
submit();
// submit is memoized, so useEffect won&apos;t be triggered on
every re-render
}, [submit]);
return ...
}
```


&lt;p&gt;Exactly the same story with &lt;code&gt;useMemo&lt;/code&gt; , only in this case, I need to
return the function I want to memoize:&lt;/p&gt;

```js
const submit = useMemo(() =&gt; {
return () =&gt; {
// this is out submit function - it&apos;s returned from the
function that is passed to memo
};
}, []);
```


&lt;p&gt;As you can see, there is a slight difference in the API. &lt;code&gt;useCallback&lt;/code&gt;
accepts the function that we want to memoize as the first argument,
while &lt;code&gt;useMemo&lt;/code&gt; accepts a function and memoizes its return value.
There is also a slight difference in their behavior because of that.
Since both hooks accept a function as the first argument, and since we
declare these functions inside a React component, that means on every
re-render, this function as the first argument will always be re-created.
It&amp;#39;s your normal JavaScript, nothing to do with React. If I declare a
function that accepts another function as an argument and then call it
multiple times with an inline function, that inline function will be re-
created from scratch with each call.&lt;/p&gt;

```js
// function that accepts a function as a first argument
const func = (callback) =&gt; {
// do something with this callback here
};
// function as an argument - first call
func(() =&gt; {});
// function as an argument - second call, new function as an
argument
func(() =&gt; {});
```


&lt;p&gt;And our hooks are just functions integrated into the React lifecycle,
nothing more.
So in order to return exactly the same reference in the &lt;code&gt;useCallback&lt;/code&gt;
hook, React does something like this:&lt;/p&gt;

```js
let cachedCallback;
const func = (callback) =&gt; {
if (dependenciesEqual()) {
return cachedCallback;
}
cachedCallback = callback;
return callback;
};
```


&lt;p&gt;It caches the very first function that is passed as an argument and then
just returns it every time if the dependencies of the hook haven&amp;#39;t
changed. And if dependencies have changed, it updates the cache and
returns the refreshed function.
With &lt;code&gt;useMemo&lt;/code&gt; , it&amp;#39;s pretty much the same, only instead of returning the
function, React calls it and returns the result:&lt;/p&gt;

```js
let cachedResult;
const func = (callback) =&gt; {
if (dependenciesEqual()) {
return cachedResult;
}
cachedResult = callback();
return cachedResult;
};
```


&lt;p&gt;The real implementation is slightly more complex, of course, but this
is the basic idea.
Why is all of this important? For real-world applications, it&amp;#39;s not, other
than for understanding the difference in the API. However, there is this
belief that sometimes pops up here and there that &lt;code&gt;useMemo&lt;/code&gt; is better
for performance than &lt;code&gt;useCallback&lt;/code&gt; , since &lt;code&gt;useCallback&lt;/code&gt; re-creates
the function passed to it with each re-render, and &lt;code&gt;useMemo&lt;/code&gt; doesn&amp;#39;t do
that. As you can see, this is not true. The function in the first argument
will be re-created for both of them.
The only time that I can think of where it would actually matter, in
theory, is when we pass as the first argument not the function itself, but
a result of another function execution hardcoded inline. Basically this:&lt;/p&gt;

```js
const submit = useCallback(something(), []);
```


&lt;p&gt;In this case, the &lt;code&gt;something&lt;/code&gt; function will be called every re-render,
even though the &lt;code&gt;submit&lt;/code&gt; reference won&amp;#39;t change. So avoid doing
expensive calculations in those functions.&lt;/p&gt;
&lt;h1&gt;Antipattern: memoizing props&lt;/h1&gt;
&lt;p&gt;The second most popular use case for memoization hooks, after
memoized values as dependencies, is passing them to props. You surely
have seen code like this:&lt;/p&gt;

```js
const Component = () =&gt; {
const onClick = useCallback(() =&gt; {
// do something on click
}, []);
return &lt;button onClick={onClick}&gt;click me&lt;/button&gt;;
};
```


&lt;p&gt;Unfortunately, this &lt;code&gt;useCallback&lt;/code&gt; here is just useless. There is this
widespread belief that even ChatGPT seems to hold, that memoizing
props prevents components from re-rendering. But as we know already
from the previous chapters, if a component re-renders, every component
inside that component will also re-render.&lt;/p&gt;
&lt;p&gt;So whether we wrap our &lt;code&gt;onClick&lt;/code&gt; function in &lt;code&gt;useCallback&lt;/code&gt; or not
doesn&amp;#39;t matter at all here. All we did was make React do a little more
work and make our code a little harder to read. When it&amp;#39;s just one
&lt;code&gt;useCallback&lt;/code&gt; , it doesn&amp;#39;t look that bad. But it&amp;#39;s never just one, is it?
There will be another, then another, they will start depending on each
other, and before you know it, the logic in the app is just buried under
the incomprehensible and undebuggable mess of &lt;code&gt;useMemo&lt;/code&gt; and
&lt;code&gt;useCallback&lt;/code&gt; .&lt;/p&gt;
&lt;p&gt;There are only two major use cases where we actually need to memoize
props on a component. The first one is when this prop is used as a
dependency in another hook in the downstream component.&lt;/p&gt;

```js
const Parent = () =&gt; {
// this needs to be memoized!
// Child uses it inside useEffect
const fetch = () =&gt; {};
return ;
};
const Child = ({ onMount }) =&gt; {
useEffect(() =&gt; {
onMount();
}, [onMount]);
};
```


&lt;p&gt;This should be self-explanatory: if a non-primitive value goes into a
dependency, it should have a stable reference between re-renders, even if
it comes from a chain of props.&lt;/p&gt;
&lt;p&gt;And the second one is when a component is wrapped in &lt;code&gt;React.memo&lt;/code&gt;&lt;/p&gt;
&lt;h1&gt;What is React.memo&lt;/h1&gt;
&lt;p&gt;&lt;code&gt;React.memo&lt;/code&gt; or just &lt;code&gt;memo&lt;/code&gt; is a very useful util that React gives us. It
allows us to memoize the component itself. If a component&amp;#39;s re-render is
triggered by its parent (and only then), and if this component is wrapped
in &lt;code&gt;React.memo&lt;/code&gt; , then and only then will React stop and check its
props. If none of the props change, then the component will not be re-
rendered, and the normal chain of re-renders will be stopped.&lt;/p&gt;

&lt;p&gt;This is again the case when React performs that comparison we talked
about at the beginning of the chapter. If even one of the props has
changed, then the component wrapped in &lt;code&gt;React.memo&lt;/code&gt; will be re-
rendered as usual:&lt;/p&gt;

```js
const Child = ({ data, onChange }) =&gt; {};
const ChildMemo = React.memo(Child);
const Component = () =&gt; {
// object and function declared inline
// will change with every re-render
return 
{...}} /&gt;
}
```


&lt;p&gt;And in the case of the example above, &lt;code&gt;data&lt;/code&gt; and &lt;code&gt;onChange&lt;/code&gt; are
declared inline, so they will change with every re-render.&lt;/p&gt;
&lt;p&gt;This is where &lt;code&gt;useMemo&lt;/code&gt; and &lt;code&gt;useCallback&lt;/code&gt; shine:&lt;/p&gt;

```js
const Child = ({ data, onChange }) =&gt; {};
const ChildMemo = React.memo(Child);
const Component = () =&gt; {
const data = useMemo(() =&gt; ({ ... }), []); // some object
const onChange = useCallback(() =&gt; {}, []); // some callback
// data and onChange now have stable reference
// re-renders of ChildMemo will be prevented
return 
}
```


&lt;p&gt;By memoizing &lt;code&gt;data&lt;/code&gt; and &lt;code&gt;onChange&lt;/code&gt; , we&amp;#39;re preserving the reference to
those objects between re-renders. Now, when React compares props on
the &lt;code&gt;ChildMemo&lt;/code&gt; component, the check will pass, and the component
won&amp;#39;t re-render.&lt;/p&gt;
&lt;p&gt;But making sure that all props are memoized is not as easy as it sounds.
We&amp;#39;re doing it wrong in so many cases! And just one single mistake leads
to broken props check, and as a result - every &lt;code&gt;React.memo&lt;/code&gt; ,
&lt;code&gt;useCallback&lt;/code&gt; , and &lt;code&gt;useMemo&lt;/code&gt; become completely useless.&lt;/p&gt;
&lt;h1&gt;React.memo and props from props&lt;/h1&gt;
&lt;p&gt;The first and simplest case of broken memoization is props that are
passed from props. Especially when the spreading of props in
components in between is involved. Imagine you have a chain of
components like this:&lt;/p&gt;

```js
const Child = () =&gt; {};
const ChildMemo = React.memo(Child);
const Component = (props) =&gt; {
return ;
};
const ComponentInBetween = (props) =&gt; {
return ;
};
const InitialComponent = (props) =&gt; {
// this one will have state and will trigger re-render of
Component
return (

);
};
```


&lt;p&gt;How likely do you think that those who need to add that additional data
to the &lt;code&gt;InitialComponent&lt;/code&gt; will go through every single component
inside, and deeper and deeper, to check whether any of them is wrapped
in &lt;code&gt;React.memo&lt;/code&gt; ? Especially if all of those are spread among different
files and are quite complicated in implementation. Never going to
happen.&lt;/p&gt;
&lt;p&gt;But as a result, the &lt;code&gt;InitialComponent&lt;/code&gt; breaks the memoization of
the &lt;code&gt;ChildMemo&lt;/code&gt; component since it passes a non-memoized &lt;code&gt;data&lt;/code&gt;
prop to it.&lt;/p&gt;
&lt;p&gt;So unless you&amp;#39;re prepared and able to enforce the rule that every single
prop everywhere should be memoized, using the &lt;code&gt;React.memo&lt;/code&gt;
function on components has to follow certain rules.&lt;/p&gt;
&lt;h2&gt;Rule 1: never spread props that are coming from other components.&lt;/h2&gt;
&lt;p&gt;Instead of this:
&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-js&quot;&gt;const Component = (props) =&amp;gt; {
return &amp;lt;ChildMemo {...props} /&amp;gt;;
};
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;it has to be something explicit like this:&lt;/p&gt;

```js
const Component = (props) =&gt; {
return ;
};
```


&lt;h2&gt;Rule 2: avoid passing non-primitive props that are coming from other components.&lt;/h2&gt;
&lt;p&gt;Even the explicit example like the one above is still quite fragile. If any of
those props are non-memoized objects or functions, memoization will
break again.&lt;/p&gt;
&lt;h2&gt;Rule 3: avoid passing non-primitive values that are coming from custom hooks.&lt;/h2&gt;
&lt;p&gt;This seems almost contradictory to the generally accepted practice of
extracting stateful logic into custom hooks. But their convenience is a
double-edged sword here: they surely hide complexities away, but also
hide away whether the data or functions have stable references as well.
Consider this:&lt;/p&gt;

```js
const Component = () =&gt; {
const { submit } = useForm();
return ;
};
```


&lt;p&gt;The &lt;code&gt;submit&lt;/code&gt; function is hidden in the &lt;code&gt;useForm&lt;/code&gt; custom hook. And
every custom hook will be triggered on every re-render. Can you tell
from the code above whether it&amp;#39;s safe to pass that &lt;code&gt;submit&lt;/code&gt; to our
&lt;code&gt;ChildMemo&lt;/code&gt; ?&lt;/p&gt;
&lt;p&gt;Nope, you can&amp;#39;t. And chances are, it will look something like this:&lt;/p&gt;

```js
const useForm = () =&gt; {
// lots and lots of code to control the form state
const submit = () =&gt; {
// do something on submit, like data validation
};
return {
submit,
};
};
```


&lt;p&gt;By passing that &lt;code&gt;submit&lt;/code&gt; function to our &lt;code&gt;ChildMemo&lt;/code&gt; , we just broke its
memoization - from now on, it will re-render as if it&amp;#39;s not wrapped in
&lt;code&gt;React.memo&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;See how fragile this pattern is already? It gets worse.&lt;/p&gt;
&lt;h1&gt;React.memo and children&lt;/h1&gt;
&lt;p&gt;Let&amp;#39;s take a look at this code:&lt;/p&gt;

```js
const ChildMemo = React.memo(Child);
const Component = () =&gt; {
return (

&lt;div&gt;Some text here&lt;/div&gt;

);
};
```



&lt;p&gt;Seems innocent enough: a memoized component with no props, renders
some div inside, right? Well, memoization is broken here again, and the
&lt;code&gt;React.memo&lt;/code&gt; wrapper is completely useless.&lt;/p&gt;
&lt;p&gt;Remember what we discussed in Chapter 2. Elements, children as
props, and re-renders? This nice nesting syntax is nothing more than
syntax sugar for the &lt;code&gt;children&lt;/code&gt; prop. I can just rewrite this code like
this:&lt;/p&gt;

```js
const Component = () =&gt; {
return Some text here&lt;/div&gt;} /&gt;;
};
```


&lt;p&gt;and it will behave exactly the same. And as we covered in Chapter 2.
Elements, children as props, and re-renders, everything that is JSX is
just syntax sugar for &lt;code&gt;React.createElement&lt;/code&gt; and actually just an
object. In this case, it will be an object with the type &amp;quot;div&amp;quot;:&lt;/p&gt;

```bash
{
type: &quot;div&quot;,
... // the rest of the stuff
}
```


&lt;p&gt;So what we have here from a memoization and props perspective is a
component that is wrapped in &lt;code&gt;React.memo&lt;/code&gt; and has a prop with a non-
memoized object in it!&lt;/p&gt;
&lt;p&gt;In order to fix it, we need to memoize the &lt;code&gt;div&lt;/code&gt; as well:&lt;/p&gt;

```js
const Component = () =&gt; {
const content = useMemo(
() =&gt; &lt;div&gt;Some text here&lt;/div&gt;,
[],
);
return ;
};
```


&lt;p&gt;or, back to the pretty syntax:&lt;/p&gt;

```js
const Component = () =&gt; {
const content = useMemo(
() =&gt; &lt;div&gt;Some text here&lt;/div&gt;,
[],
);
return {content};
};
```


&lt;p&gt;Exactly the same story applies to children as a render prop, by the way.
This will be broken:&lt;/p&gt;

```js
const Component = () =&gt; {
return (
{() =&gt; &lt;div&gt;Some text here&lt;/div&gt;}
);
};
```


&lt;p&gt;Our children here is a function that is re-created on every re-render. Also
need to memoize it with &lt;code&gt;useMemo&lt;/code&gt; :&lt;/p&gt;

```js
const Component = () =&gt; {
const content = useMemo(
() =&gt; () =&gt; &lt;div&gt;Some text here&lt;/div&gt;,
[],
);
return {content};
};
```


&lt;p&gt;Or just use &lt;code&gt;useCallback&lt;/code&gt; :&lt;/p&gt;

```js
const Component = () =&gt; {
const content = useCallback(
() =&gt; &lt;div&gt;Some text here&lt;/div&gt;,
[],
);
return {content};
};
```


&lt;p&gt;Take a look at your app right now. How many of these have slipped
through the cracks?&lt;/p&gt;
&lt;h1&gt;React.memo and memoized children (almost)&lt;/h1&gt;
&lt;p&gt;If you went through your app, fixed all those patterns, and feel confident
that memoization is in a good state now, don&amp;#39;t rush. When has life ever
been so easy! What do you think about this one? Is it okay or broken?&lt;/p&gt;

```js
const ChildMemo = React.memo(Child);
const ParentMemo = React.memo(Parent);
const Component = () =&gt; {
return (



);
};
```


&lt;p&gt;Both of them are memoized, so it has to be okay, right? Wrong.
&lt;code&gt;ParentMemo&lt;/code&gt; will behave as if it is not wrapped in &lt;code&gt;React.memo&lt;/code&gt; - its children are actually not memoized!
Let&amp;#39;s take a closer look at what&amp;#39;s happening. As we already know,&lt;/p&gt;
&lt;p&gt;Elements are just syntax sugar for &lt;code&gt;React.createElement&lt;/code&gt; , which
returns an object with the type that points to the component. If I were
creating a &lt;code&gt;&amp;lt;Parent /&amp;gt;&lt;/code&gt; Element, it would be this:&lt;/p&gt;

```bash
{
type: Parent,
... // the rest of the stuff
}
```


&lt;p&gt;With memoized components, it&amp;#39;s exactly the same. The &lt;code&gt;&amp;lt;ParentMemo/&amp;gt;&lt;/code&gt; element will be converted into an object of a similar shape. Only the
&amp;quot;type&amp;quot; property will contain information about our &lt;code&gt;ParentMemo&lt;/code&gt; .&lt;/p&gt;
&lt;p&gt;And this object is just an object, it&amp;#39;s not memoized by itself. So again,
from the memoization and props perspective, we have a &lt;code&gt;ParentMemo&lt;/code&gt;
component that has a &lt;code&gt;children&lt;/code&gt; prop that contains a non-memoized
object. Hence, broken memoization on &lt;code&gt;ParentMemo&lt;/code&gt; .&lt;/p&gt;
&lt;p&gt;To fix it, we need to memoize the object itself:&lt;/p&gt;

```js
const Component = () =&gt; {
const child = useMemo(() =&gt; , []);
return {child};
};
```


&lt;p&gt;And then we might not even need the &lt;code&gt;ChildMemo&lt;/code&gt; at all. Depends on its
content and our intentions, of course. At least for the purpose of
preventing &lt;code&gt;ParentMemo&lt;/code&gt; from re-rendering, &lt;code&gt;ChildMemo&lt;/code&gt; is
unnecessary, and it can return back to being just a normal &lt;code&gt;Child&lt;/code&gt; &lt;/p&gt;

```js
const Component = () =&gt; {
const child = useMemo(() =&gt; , []);
return {child};
};
```



&lt;h1&gt;useMemo and expensive calculations&lt;/h1&gt;
&lt;p&gt;And the final, quite popular performance-related use case for &lt;code&gt;useMemo&lt;/code&gt;
is memoizing &amp;quot;expensive calculations.&amp;quot; In quotes, since it&amp;#39;s actually
misused quite often as well.&lt;/p&gt;
&lt;p&gt;First of all, what is an &amp;quot;expensive calculation&amp;quot;? Is concatenating strings
expensive? Or sorting an array of 300 items? Or running a regular
expression on a text of 5000 words? I don&amp;#39;t know. And you don&amp;#39;t. And no
one knows until it&amp;#39;s actually measured:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;on a device that is representative of your user base&lt;/li&gt;
&lt;li&gt;in context&lt;/li&gt;
&lt;li&gt;in comparison with the rest of the stuff that is happening at the
same time&lt;/li&gt;
&lt;li&gt;in comparison with how it was before or the ideal state&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Sorting an array of 300 items on my laptop, even with a 6x slowed-down
CPU, takes less than 2ms. But on some old Android 2 mobile phone, it
might take a second.&lt;/p&gt;
&lt;p&gt;Executing a regular expression on a text that takes 100ms feels slow. But
if it&amp;#39;s run as a result of a button click, once in a blue moon, buried
somewhere deep in the settings screen, then it&amp;#39;s almost instant. A regular
expression that takes 30ms to run seems fast enough. But if it&amp;#39;s run on
the main page on every mouse move or scroll event, it&amp;#39;s unforgivably
slow and needs to be improved.&lt;/p&gt;
&lt;p&gt;It always depends. &amp;quot;Measure first&amp;quot; should be the default thinking when
there is an urge to wrap something in &lt;code&gt;useMemo&lt;/code&gt; because it&amp;#39;s an
&amp;quot;expensive calculation.&amp;quot;&lt;/p&gt;
&lt;p&gt;The second thing to think about is React. In particular, rendering of
components in comparison to raw JavaScript calculations. More likely
than not, anything that is calculated within &lt;code&gt;useMemo&lt;/code&gt; will be an order of
magnitude faster than re-rendering actual elements anyway. For
example, sorting that array of 300 items on my laptop took less than
2ms. Re-rendering list elements from that array, even when they were
just simple buttons with some text, took more than 20ms. If I want to
improve the performance of that component, the best thing to do would
be to get rid of the unnecessary re-renders of everything, not memoizing
something that takes less than 2ms.&lt;/p&gt;
&lt;p&gt;So an addition to the &amp;quot;measure first&amp;quot; rule, when it comes to
memoization, should be: &amp;quot;don&amp;#39;t forget to measure how long it takes to re-
render component elements as well.&amp;quot; And if you wrap every JavaScript
calculation in &lt;code&gt;useMemo&lt;/code&gt; and gain 10ms from it, but re-rendering of
actual components still takes almost 200ms, then what&amp;#39;s the point? All it
does is complicate the code without any visible gain.&lt;/p&gt;
&lt;p&gt;And finally, &lt;code&gt;useMemo&lt;/code&gt; is only useful for re-renders. That&amp;#39;s the whole
point of it and how it works. If your component never re-renders, then
&lt;code&gt;useMemo&lt;/code&gt; just does nothing.&lt;/p&gt;
&lt;p&gt;More than nothing, it forces React to do additional work on the initial
render. Don&amp;#39;t forget: the very first time the &lt;code&gt;useMemo&lt;/code&gt; hook runs, when
the component is first mounted, React needs to cache it. It will use a
little bit of memory and computational power for that, which otherwise
would be free. With just one &lt;code&gt;useMemo&lt;/code&gt; , the impact won&amp;#39;t be
measurable, of course. But in large apps, with hundreds of them
scattered everywhere, it actually can measurably slow down the initial
render. It will be death by a thousand cuts in the end.&lt;/p&gt;
&lt;h1&gt;Key takeaways&lt;/h1&gt;
&lt;p&gt;Well, that&amp;#39;s depressing. Does all of this mean we shouldn&amp;#39;t use
memoization? Not at all. It can be a very valuable tool in our
performance battle. But considering so many caveats and complexities
that surround it, I would recommend using composition-based
optimization techniques as much as possible first. &lt;code&gt;React.memo&lt;/code&gt; should
be the last resort when all other things have failed.&lt;/p&gt;
&lt;p&gt;And let&amp;#39;s remember:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;React compares objects/arrays/functions by their reference, not
their value. That comparison happens in hooks&amp;#39; dependencies and
in props of components wrapped in &lt;code&gt;React.memo&lt;/code&gt; .&lt;/li&gt;
&lt;li&gt;The inline function passed as an argument to either &lt;code&gt;useMemo&lt;/code&gt; or
&lt;code&gt;useCallback&lt;/code&gt; will be re-created on every re-render.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;useCallback&lt;/code&gt; memoizes that function itself, &lt;code&gt;useMemo&lt;/code&gt;
memoizes the result of its execution.&lt;/li&gt;
&lt;li&gt;Memoizing props on a component makes sense only when:&lt;ul&gt;
&lt;li&gt;This component is wrapped in &lt;code&gt;React.memo&lt;/code&gt; .&lt;/li&gt;
&lt;li&gt;This component uses those props as dependencies in any of
the hooks.&lt;/li&gt;
&lt;li&gt;This component passes those props down to other
components, and they have either of the situations from
above.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;If a component is wrapped in &lt;code&gt;React.memo&lt;/code&gt; and its re-render is
triggered by its parent, then React will not re-render this
component if its props haven&amp;#39;t changed. In any other case, re-
render will proceed as usual.&lt;/li&gt;
&lt;li&gt;Memoizing all props on a component wrapped in &lt;code&gt;React.memo&lt;/code&gt;
is harder than it seems. Avoid passing non-primitive values that
are coming from other props or hooks to it.&lt;/li&gt;
&lt;li&gt;When memoizing props, remember that &amp;quot;children&amp;quot; is also a non-
primitive prop that needs to be memoized.&lt;/li&gt;
&lt;/ul&gt;
]]></content:encoded>
            <dc:creator>Rami Chabchoub</dc:creator>
        </item>
        <item>
            <title><![CDATA[Practical React Query]]></title>
            <description><![CDATA[A practical guide to React Query, including how to use it, how it works, and how to get the most out of it.]]></description>
            <link>https://www.ramicode.com/en/articles/practical-react-query</link>
            <guid isPermaLink="false">practical-react-query</guid>
            <dc:creator><![CDATA[Rami Chabchoub]]></dc:creator>
            <pubDate>Mon, 15 Jan 2024 00:00:00 GMT</pubDate>
            <content:encoded><![CDATA[&lt;p&gt;When GraphQL and especially Apollo Client became popular in ca. 2018, there was a lot of fuss about it completely replacing redux, and the question  Is Redux dead yet? has beed asked a lot.&lt;/p&gt;
&lt;p&gt;I distictly remember not understanding what this was all about. Why would some data fetching library replace your global state manager? What doas one even have to do with the other?&lt;/p&gt;
&lt;p&gt;I was under the impression that GraphQL clients like Apollo would only fetch the data for you, similiar to what e.g. axios does for REST, and that you would still obviously need some way of making that data accessible to your application.&lt;/p&gt;
&lt;p&gt;I couldn&amp;#39;t have been more wrong.&lt;/p&gt;
&lt;h1&gt;Client State vs. Server State&lt;/h1&gt;
&lt;p&gt;What Apollo gives you is not just the ability to describe which data you want and to fetch that data, it also comes with a cache for that server data. This means that you can just use the same &lt;code&gt;useQuery&lt;/code&gt; hook in multiple components, and it will only fetch data once and then subsequently return it from the cache.&lt;/p&gt;
&lt;p&gt;This sounds very familiar with what we, and probably many other teams as well, have mainly been using &lt;code&gt;redux&lt;/code&gt; for: Fetch data from the server and make it available everywhere.&lt;/p&gt;
&lt;p&gt;So it seems that we have always been treating this server state like any other client state. Except that when it comes to server state (think: A list of articles that you fetch, the details of a User you want to display, ...), your app does not own it. We have only borrowed it to display the most recent version of it on the screen for the user. It is the server who owns the data.&lt;/p&gt;
&lt;p&gt;To me, that introduced a paradigm shift in how to think about data. If we can leverage the cache to display data that we do not own, there isn&amp;#39;t really much left that is real client state that also needs to be made available to the whole app. That made me understand why many think that Apollo can replace redux in lots of instances.&lt;/p&gt;
&lt;h1&gt;React Query&lt;/h1&gt;
&lt;p&gt;I have never had the chance to use GraphQL. We have an existing REST API, don&amp;#39;t really experience problems with over-fetching, it just works, etc. Clearly, there aren&amp;#39;t enough pain points for us to warrant a switch, especially given that you&amp;#39;d also have to adapt the backend, which isn&amp;#39;t quite so simple.&lt;/p&gt;
&lt;p&gt;Yet I still envied the simplicity of how data fetching can look like on the frontend, including the handling of loading and error states. If only there were something similar in React for REST APIs...&lt;/p&gt;
&lt;p&gt;Enter React Query.&lt;/p&gt;
&lt;p&gt;Made by the open sourcerer Tanner Linsley in late 2019, React Query takes the good parts of Apollo and brings them to REST.
It works with any function that returns a Promise and embraces the stale-while-revalidate caching strategy.
The library operates on sane defaults that try to keep your data as fresh as possible while at the same time showing data to the user as early as possible, making it feel near instant at times and thus providing a great UX.
On top of that, it is also very flexible and lets you customize various settings for when the defaults are not enough.&lt;/p&gt;
&lt;p&gt;This article is not going to be an introduction to React Query though.&lt;/p&gt;
&lt;p&gt;I think the docs are great at explaining Guides &amp;amp; Concepts, there are Videos from various Talks that you can watch, and Tanner has a React Query Essentials Course you can take if you want to get familiar with the library.&lt;/p&gt;

I&apos;ve been working on a brand new course together with ui.dev. If you enjoy the content I&apos;ve been creating so far, you&apos;ll love query.gg.



&lt;p&gt;I want to focus more on some practical tips that go beyond the docs, which might be useful when you are already working with the library.
These are things I have picked up over the last couple of months when I was not only actively using the library at work, but also got involved in the React Query community, answering questions on Discord and in GitHub Discussions.&lt;/p&gt;
&lt;h1&gt;The Defaults explained&lt;/h1&gt;
&lt;p&gt;I believe the React Query Defaults are very well-chosen, but they can catch you off guard from time to time, especially at the beginning.&lt;/p&gt;
&lt;p&gt;First of all: React Query does not invoke the &lt;code&gt;queryFn&lt;/code&gt; on every re-render, even with the default &lt;code&gt;staleTime&lt;/code&gt; of zero.
Your app can re-render for various reasons at any time, so fetching every time would be insane!&lt;/p&gt;

Always code for re-renders, and a lot of them. I like to call it render resiliency.


&lt;p&gt;If you see a refetch that you are not expecting, it is likely because you just focused the window and React Query is doing a &lt;code&gt;refetchOnWindowFocus&lt;/code&gt;, which is a great feature for production: If the user goes to a different browser tab, and then comes back to your app, a background refetch will be triggered automatically, and data on the screen will be updated if something has changed on the server in the meantime.
All of this happens without a loading spinner being shown, and your component will not re-render if the data is the same as you currently have in the cache.&lt;/p&gt;
&lt;p&gt;During development, this will probably be triggered more frequently, especially because focusing between the Browser DevTools and your app will also cause a fetch, so be aware of that.&lt;/p&gt;

Since React Query v5, `refetchOnWindowFocus` no longer listens to the `focus` event - the `visibilitychange` event is used exclusively. This means you&apos;ll get fewer unwanted re-fetches in development mode, while still retaining the trigger for most production cases. It also fixes a bunch of issues as shown here.


&lt;p&gt;Secondly, there seems to be a bit of confusion between &lt;code&gt;gcTime&lt;/code&gt; and &lt;code&gt;staleTime&lt;/code&gt;, so let me try to clear that up:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;staleTime&lt;/code&gt;: The duration until a query transitions from fresh to stale. As long as the query is fresh, data will always be read from the cache only - no network request will happen! If the query is stale (which per default is: instantly), you will still get data from the cache, but a background refetch can happen under certain conditions.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;gcTime&lt;/code&gt;: The duration until inactive queries will be removed from the cache. This defaults to 5 minutes. Queries transition to the inactive state as soon as there are no observers registered, so when all components which use that query have unmounted.Most of the time, if you want to change one of these settings, it&amp;#39;s the staleTime that needs adjusting. I have rarely ever needed to tamper with the gcTime. There is a good explanation by example in the docs as well.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;

`gcTime` was previously known as `cacheTime`, but it got renamed in v5 to better reflect what it&apos;s doing.


&lt;h1&gt;Use the React Query DevTools&lt;/h1&gt;
&lt;p&gt;This will help you immensely in understanding the state a query is in.
The DevTools will also tell you what data is currently in the cache, so you&amp;#39;ll have an easier time debugging.
In addition to that, I have found that it helps to throttle your network connection in the browser DevTools if you want to better recognize background refetches, since dev-servers are usually pretty fast.&lt;/p&gt;
&lt;h1&gt;Treat the query key like a dependency array&lt;/h1&gt;
&lt;p&gt;I am referring to the dependency array of the useEffect hook here, which I assume you are familiar with.&lt;/p&gt;
&lt;p&gt;Why are these two similar?&lt;/p&gt;
&lt;p&gt;Because React Query will trigger a refetch whenever the query key changes.
So when we pass a variable parameter to our &lt;code&gt;queryFn&lt;/code&gt;, we almost always want to fetch data when that value changes.
Instead of orchestrating complex effects to manually trigger a refetch, we can utilize the query key:&lt;/p&gt;

```typescript showLineNumbers
type State = &apos;all&apos; | &apos;open&apos; | &apos;done&apos;
type Todo = {
  id: number
  state: State
}
type Todos = ReadonlyArray

&lt;p&gt;const fetchTodos = async (state: State): Promise =&amp;gt; {
  const response = await axios.get(&lt;code&gt;todos/${state}&lt;/code&gt;)
  return response.data
}&lt;/p&gt;
&lt;p&gt;export const useTodosQuery = (state: State) =&amp;gt;
  useQuery({
    queryKey: [&amp;#39;todos&amp;#39;, state],
    queryFn: () =&amp;gt; fetchTodos(state),
  })&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;/CodeBlock&amp;gt;

Here, imagine that our UI displays a list of todos along with a filter option.
We would have some local state to store that filtering, and as soon as the user changes their selection, we would update that local state, and React Query will automatically trigger the refetch for us, because the query key changes.
We are thus keeping the user&amp;#39;s filter selection in sync with the query function, which is very similar to what a dependency array represents for useEffect.
I don&amp;#39;t think I have ever passed a variable to the `queryFn` that was not part of the `queryKey`, too.

# A new cache entry

Because the query key is used as a key for the cache, you will get a new cache entry when you switch from &amp;#39;all&amp;#39; to &amp;#39;done&amp;#39;, and that will result in a hard loading state (probably showing a loading spinner) when you switch for the first time.
This is certainly not ideal, so if possible, we can try to pre-fill the newly created cache entry with &amp;lt;A href=&amp;quot;https://tanstack.com/query/latest/docs/framework/react/guides/initial-query-data#initial-data-from-cache&amp;quot;&amp;gt;initialData&amp;lt;/A&amp;gt;.
The above example is perfect for that, because we can do some client side pre-filtering on our todos:

&amp;lt;CodeBlock title=&amp;quot;pre-filtering&amp;quot;&amp;gt;
```typescript showLineNumbers {17-26}
type State = &amp;#39;all&amp;#39; | &amp;#39;open&amp;#39; | &amp;#39;done&amp;#39;
type Todo = {
  id: number
  state: State
}
type Todos = ReadonlyArray&amp;lt;Todo&amp;gt;

const fetchTodos = async (state: State): Promise&amp;lt;Todos&amp;gt; =&amp;gt; {
  const response = await axios.get(`todos/${state}`)
  return response.data
}

export const useTodosQuery = (state: State) =&amp;gt; {
  useQuery({
    queryKey: [&amp;#39;todos&amp;#39;, state],
    queryFn: () =&amp;gt; fetchTodos(state),
    initialData: () =&amp;gt; {
      const allTodos = queryClient.getQueryData&amp;lt;Todos&amp;gt;([
        &amp;#39;todos&amp;#39;,
        &amp;#39;all&amp;#39;,
      ])
      const filteredData =
        allTodos?.filter((todo) =&amp;gt; todo.state === state) ?? []

      return filteredData.length &amp;gt; 0 ? filteredData : undefined
    },
  })
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;Now, every time the user switches between states, if we don&amp;#39;t have data yet, we try to show data from the &amp;#39;all todos&amp;#39; cache.
We can instantly show the &amp;#39;done&amp;#39; todos that we have to the user, and they will still see the updated list once the background fetch finishes.&lt;/p&gt;
&lt;p&gt;I think this is a great ux improvement for just a few lines of code.&lt;/p&gt;
&lt;h1&gt;Keep server and client state separate&lt;/h1&gt;
&lt;p&gt;This goes hand in hand with putting-props-to-use-state, an article I have written last month: If you get data from &lt;code&gt;useQuery&lt;/code&gt;, try not to put that data into local state.
The main reason is that you implicitly opt out of all background updates that React Query does for you, because the state &amp;quot;copy&amp;quot; will not update with it.&lt;/p&gt;
&lt;p&gt;This is fine if you want to e.g. fetch some default values for a Form, and render your Form once you have data.
Background updates are very unlikely to yield something new, and even if, your Form has already been initialized.
So if you do that on purpose, make sure to not fire off unnecessary background refetches by setting &lt;code&gt;staleTime&lt;/code&gt;:&lt;/p&gt;

```typescript showLineNumbers
const App = () =&gt; {
  const { data } = useQuery({
    queryKey: [&apos;key&apos;],
    queryFn,
    staleTime: Infinity,
  })

&lt;p&gt;  return data ?  : null
}&lt;/p&gt;
&lt;p&gt;const MyForm = ({ initialData }) =&amp;gt; {
  const [data, setData] = React.useState(initialData)
  ...
}&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;/CodeBlock&amp;gt;

This concept will be a bit harder to follow through when you display data that you also want to allow the user to edit, but it has many advantages.
I have prepared a little codesandbox example:

&amp;lt;IFrame 
  src=&amp;quot;https://codesandbox.io/embed/inspiring-mayer-rp3jx?fontsize=14&amp;amp;hidenavigation=1&amp;amp;theme=dark&amp;amp;view=preview&amp;quot;
  height={500}
/&amp;gt;

The important part of this demo is that we never put the value that we get from React Query into local state.
This makes sure that we always see the latest data, because there is no local &amp;quot;copy&amp;quot; of it.

# The enabled option is very powerful

The `useQuery` hook has many options that you can pass in to customize its behaviour, and the `enabled` option is a very powerful one that enables you to do many cool things (pun intended).
Here is a short list of things that we were able to accomplish thanks to this option:

* &amp;lt;A href=&amp;quot;https://tanstack.com/query/latest/docs/framework/react/guides/dependent-queries&amp;quot;&amp;gt;Dependent Queries&amp;lt;/A&amp;gt;

    Fetch data in one query and have a second query only run once we have successfully obtained data from the first query.

* Turn queries on and off

    We have one query that polls data regularly thanks to `refetchInterval`, but we can temporarily pause it if a Modal is open to avoid updates in the back of the screen.

* Wait for user input

    Have some filter criteria in the query key, but disable it for as long as the user has not applied their filters.

* Disable a query after some user input

    e.g. if we then have a draft value that should take precedence over the server data. See the above example.

# Don&amp;#39;t use the queryCache as a local state manager

If you tamper with the queryCache (`queryClient.setQueryData`), it should only be for optimistic updates or for writing data that you receive from the backend after a mutation.
Remember that every background refetch might override that data, so &amp;lt;A href=&amp;quot;https://react.dev/reference/react/useState&amp;quot;&amp;gt;use&amp;lt;/A&amp;gt; &amp;lt;A href=&amp;quot;https://zustand-demo.pmnd.rs/&amp;quot;&amp;gt;something&amp;lt;/A&amp;gt; &amp;lt;A href=&amp;quot;https://redux.js.org/&amp;quot;&amp;gt;else&amp;lt;/A&amp;gt; for local state.

# Create custom hooks

Even if it&amp;#39;s only for wrapping one `useQuery` call, creating a custom hook usually pays off because:

* You can keep the actual data fetching out of the ui, but co-located with your `useQuery` call.
* You can keep all usages of one query key (and potentially type definitions) in one file.
* If you need to tweak some settings or add some data transformation, you can do that in one place.
* You have already seen an example of that in the todos queries above.

You have already seen an example of that in the &amp;lt;A href=&amp;quot;#treat-the-query-key-like-a-dependency-array&amp;quot;&amp;gt;todos queries above&amp;lt;/A&amp;gt;.

---

I hope that these practical tips will help you to get started with React Query, so go check it out :)
&lt;/code&gt;&lt;/pre&gt;
]]></content:encoded>
            <dc:creator>Rami Chabchoub</dc:creator>
        </item>
        <item>
            <title><![CDATA[React Native Tech Stack 2025: The Ultimate Guide to Building Modern Mobile Apps]]></title>
            <description><![CDATA[A comprehensive guide to the best React Native tech stack for 2025, including the latest libraries, tools, and frameworks.]]></description>
            <link>https://www.ramicode.com/en/articles/react-native-tech-stack-2025</link>
            <guid isPermaLink="false">react-native-tech-stack-2025</guid>
            <dc:creator><![CDATA[Rami Chabchoub]]></dc:creator>
            <pubDate>Fri, 24 Jan 2025 00:00:00 GMT</pubDate>
            <content:encoded><![CDATA[&lt;h1&gt;React Native Tech Stack 2025: The Ultimate Guide&lt;/h1&gt;
&lt;p&gt;The mobile development landscape in 2025 has evolved significantly, and React Native stands at the forefront of this evolution. As the framework becomes more robust, performant, and stable, choosing the right tools and packages for your project has never been more crucial. This comprehensive guide will help you navigate the vast ecosystem of React Native development and make informed decisions for your next project.&lt;/p&gt;
&lt;h2&gt;Core Development Setup&lt;/h2&gt;
&lt;p&gt;When starting a new React Native project in 2025, there are two fundamental choices that form the foundation of your development setup:&lt;/p&gt;
&lt;h3&gt;Expo Framework&lt;/h3&gt;
&lt;p&gt;Expo has emerged as the de-facto standard for React Native development in 2025. Here&amp;#39;s why you should choose Expo for your next project:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Official Recognition&lt;/strong&gt;: Expo is now the recommended framework in the React Native documentation&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Production Ready&lt;/strong&gt;: Major companies have adopted Expo for their production applications&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Developer Experience&lt;/strong&gt;: Provides a comprehensive development environment out of the box&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Framework Benefits&lt;/strong&gt;: Avoiding the need to build your own framework from scratch&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Migration Friendly&lt;/strong&gt;: Even legacy projects using the React Native CLI can gradually migrate to Expo&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;TypeScript Integration&lt;/h3&gt;
&lt;p&gt;TypeScript has become an essential tool in modern React Native development. Here&amp;#39;s why you should embrace it:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Enhanced Developer Experience&lt;/strong&gt;: Get real-time feedback from your IDE&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Bug Prevention&lt;/strong&gt;: Catch type-related errors before they reach production&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Maintainability&lt;/strong&gt;: Makes your codebase more maintainable and self-documenting&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Practical Usage&lt;/strong&gt;: Focus on practical type implementations rather than complex type patterns&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;IDE Support&lt;/strong&gt;: Excellent integration with modern development environments&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;While it&amp;#39;s possible to develop React Native applications without TypeScript, the benefits it brings to your development workflow are invaluable. The type system helps prevent common errors and provides better code documentation, making it easier for teams to collaborate and maintain code over time.&lt;/p&gt;
&lt;h2&gt;Navigation Solutions&lt;/h2&gt;
&lt;p&gt;When it comes to navigation in React Native, there are two main contenders in 2025:&lt;/p&gt;
&lt;h3&gt;Expo Router vs React Navigation&lt;/h3&gt;
&lt;p&gt;Both solutions are powerful, but they serve different needs:&lt;/p&gt;
&lt;h4&gt;Expo Router&lt;/h4&gt;
&lt;p&gt;Expo Router has become the preferred choice for modern React Native applications. Here&amp;#39;s why:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;File-based Routing&lt;/strong&gt;: Intuitive and familiar for web developers&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Cross-platform Focus&lt;/strong&gt;: Excellent support for iOS, Android, and web&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Advanced Features&lt;/strong&gt;: &lt;ul&gt;
&lt;li&gt;API routes support&lt;/li&gt;
&lt;li&gt;RC (Remote Components) support&lt;/li&gt;
&lt;li&gt;Built-in layouts system&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Future-proof&lt;/strong&gt;: Regular updates and new features from the Expo team&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;React Navigation&lt;/h4&gt;
&lt;p&gt;React Navigation remains a solid choice, especially if:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;You&amp;#39;re focusing solely on native mobile platforms&lt;/li&gt;
&lt;li&gt;You prefer a more traditional screen-based approach&lt;/li&gt;
&lt;li&gt;You need more granular control over navigation&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Enhanced Navigation Components&lt;/h3&gt;
&lt;p&gt;For tab-based navigation, consider using React Native Bottom Tabs, which provides:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Native bottom tabs implementation&lt;/li&gt;
&lt;li&gt;Smooth animations on both platforms&lt;/li&gt;
&lt;li&gt;Better performance than custom implementations&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;UI and Styling Solutions&lt;/h2&gt;
&lt;p&gt;The UI and styling landscape in React Native has evolved to offer multiple approaches, each with its own strengths:&lt;/p&gt;
&lt;h3&gt;Modern Styling Solutions&lt;/h3&gt;

1. **NativeWind**
NativeWind brings Tailwind CSS to React Native:
- Familiar Tailwind syntax
- Growing ecosystem with NativeWind UI components
- Strong community adoption

&lt;ol start=&quot;2&quot;&gt;
&lt;li&gt;&lt;strong&gt;UniStyles&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;UniStyles offers:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Familiar StyleSheet-like API&lt;/li&gt;
&lt;li&gt;Enhanced functionality&lt;/li&gt;
&lt;li&gt;C++ bindings for optimal performance&lt;/li&gt;
&lt;li&gt;Version 3.0 with new features&lt;/li&gt;
&lt;/ul&gt;
&lt;ol start=&quot;3&quot;&gt;
&lt;li&gt;&lt;strong&gt;Tamagui&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Tamagui provides:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Cross-platform styling solution&lt;/li&gt;
&lt;li&gt;Optimized compiler&lt;/li&gt;
&lt;li&gt;Built-in component library&lt;/li&gt;
&lt;li&gt;Strong performance optimizations&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Component Libraries&lt;/h3&gt;
&lt;p&gt;While traditional component libraries like React Native Paper and React Native Elements still have their place, modern development tends to favor more flexible solutions:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;NativeWind UI&lt;/strong&gt;: Pre-built components using NativeWind&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;React Native Reusables&lt;/strong&gt;: Chakra-inspired components for React Native&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Tamagui Components&lt;/strong&gt;: Cross-platform optimized components&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Choosing the Right Solution&lt;/h3&gt;
&lt;p&gt;Your choice should depend on:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Project requirements&lt;/li&gt;
&lt;li&gt;Team expertise&lt;/li&gt;
&lt;li&gt;Performance needs&lt;/li&gt;
&lt;li&gt;Cross-platform requirements&lt;/li&gt;
&lt;li&gt;Design system flexibility&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For most modern projects, NativeWind offers an excellent balance of features, familiarity, and flexibility. However, UniStyles provides a more native-feeling approach, while Tamagui excels in cross-platform scenarios with its optimization features.&lt;/p&gt;
&lt;h2&gt;Animation Libraries&lt;/h2&gt;
&lt;p&gt;Animation is crucial for creating engaging mobile experiences. Here are the top choices for 2025:&lt;/p&gt;
&lt;h3&gt;React Native Reanimated&lt;/h3&gt;
&lt;p&gt;React Native Reanimated remains the gold standard for animations:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;High-performance native animations&lt;/li&gt;
&lt;li&gt;Declarative API&lt;/li&gt;
&lt;li&gt;Excellent TypeScript support&lt;/li&gt;
&lt;li&gt;Rich ecosystem and community&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Moti&lt;/h3&gt;
&lt;p&gt;Moti offers a simpler approach to animations:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Built on top of Reanimated&lt;/li&gt;
&lt;li&gt;Easier learning curve&lt;/li&gt;
&lt;li&gt;Preset animations&lt;/li&gt;
&lt;li&gt;Great for quick implementations&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;State Management&lt;/h2&gt;
&lt;p&gt;Modern React Native apps require different state management solutions for different use cases:&lt;/p&gt;
&lt;h3&gt;Server State Management&lt;/h3&gt;
&lt;p&gt;TanStack Query (formerly React Query) is the clear winner for managing server state:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Powerful data synchronization&lt;/li&gt;
&lt;li&gt;Built-in caching&lt;/li&gt;
&lt;li&gt;Automatic background updates&lt;/li&gt;
&lt;li&gt;Optimistic updates&lt;/li&gt;
&lt;li&gt;Request deduplication&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;Alternative: Redux Toolkit Query&lt;/h4&gt;

If your project is already using Redux for client state management, Redux Toolkit Query (RTK Query) is an excellent alternative:
- Tight integration with Redux ecosystem
- Code generation for API endpoints
- Automatic cache management
- Built-in TypeScript support
- Familiar Redux patterns

&lt;p&gt;The choice between TanStack Query and RTK Query often depends on your existing architecture:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Choose TanStack Query for new projects or when you prefer a standalone solution&lt;/li&gt;
&lt;li&gt;Use RTK Query when you&amp;#39;re already invested in the Redux ecosystem&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Application State Management&lt;/h3&gt;
&lt;p&gt;Several solutions exist for managing client-side state:&lt;/p&gt;

1. **Zustand**
Zustand is the preferred choice for most applications:
- Simple and lightweight
- Familiar store concept
- Great TypeScript support
- Strong community adoption

&lt;ol start=&quot;2&quot;&gt;
&lt;li&gt;&lt;strong&gt;Legend State&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Legend State for local-first applications:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Built-in sync capabilities&lt;/li&gt;
&lt;li&gt;Supabase integration&lt;/li&gt;
&lt;li&gt;Offline-first approach&lt;/li&gt;
&lt;/ul&gt;
&lt;ol start=&quot;3&quot;&gt;
&lt;li&gt;&lt;strong&gt;Context API&lt;/strong&gt;
React&amp;#39;s built-in Context API might be sufficient for:&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;Simple state requirements&lt;/li&gt;
&lt;li&gt;Small to medium applications&lt;/li&gt;
&lt;li&gt;Component-level state sharing&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Data Storage Solutions&lt;/h2&gt;
&lt;h3&gt;Database ORM Solutions&lt;/h3&gt;
&lt;h4&gt;Drizzle ORM&lt;/h4&gt;
&lt;p&gt;Drizzle ORM has emerged as the modern, lightweight alternative to traditional ORMs in 2025:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Key Features&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;TypeScript-first approach&lt;/li&gt;
&lt;li&gt;SQL-like query builder&lt;/li&gt;
&lt;li&gt;Zero abstractions over SQL&lt;/li&gt;
&lt;li&gt;Significantly smaller bundle size&lt;/li&gt;
&lt;li&gt;Better performance than traditional ORMs&lt;/li&gt;
&lt;li&gt;Built-in schema migrations&lt;/li&gt;
&lt;li&gt;Native Edge runtime support&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Benefits&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Type-safe database queries&lt;/li&gt;
&lt;li&gt;Minimal runtime overhead&lt;/li&gt;
&lt;li&gt;Direct SQL-like syntax&lt;/li&gt;
&lt;li&gt;Easy integration with SQLite and Postgres&lt;/li&gt;
&lt;li&gt;Excellent developer experience&lt;/li&gt;
&lt;li&gt;Strong community growth&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;While Prisma has been widely used in previous years, Drizzle represents the future of database interactions with its lightweight approach and modern architecture. It&amp;#39;s particularly well-suited for React Native applications due to its:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Smaller bundle size impact&lt;/li&gt;
&lt;li&gt;Better performance characteristics&lt;/li&gt;
&lt;li&gt;Simpler mental model&lt;/li&gt;
&lt;li&gt;Native Edge compatibility&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;Migration from Prisma&lt;/h4&gt;
&lt;p&gt;If you&amp;#39;re coming from Prisma, Drizzle offers several advantages:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;More predictable query generation&lt;/li&gt;
&lt;li&gt;Faster query execution&lt;/li&gt;
&lt;li&gt;No need for additional CLI tools&lt;/li&gt;
&lt;li&gt;Direct SQL-like syntax that&amp;#39;s easier to debug&lt;/li&gt;
&lt;li&gt;Better suited for edge environments&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Supabase&lt;/h3&gt;
&lt;p&gt;Supabase has become the go-to backend solution for React Native applications in 2025:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Core Features&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;PostgreSQL Database with real-time capabilities&lt;/li&gt;
&lt;li&gt;Built-in authentication and user management&lt;/li&gt;
&lt;li&gt;Edge Functions for serverless computing&lt;/li&gt;
&lt;li&gt;Storage solution for files and media&lt;/li&gt;
&lt;li&gt;Auto-generated TypeScript types&lt;/li&gt;
&lt;li&gt;Official React Native SDK&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Key Benefits&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Excellent offline-first capabilities&lt;/li&gt;
&lt;li&gt;Row Level Security (RLS) for data protection&lt;/li&gt;
&lt;li&gt;WebSocket connections for real-time features&lt;/li&gt;
&lt;li&gt;Competitive pricing with generous free tier&lt;/li&gt;
&lt;li&gt;Strong TypeScript integration&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;SQLite with Expo&lt;/h3&gt;

Expo SQLite provides a reliable and easy-to-use local database solution:

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Key Features&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Built into Expo SDK&lt;/li&gt;
&lt;li&gt;Full SQLite API access&lt;/li&gt;
&lt;li&gt;Async/Sync API support&lt;/li&gt;
&lt;li&gt;Transaction support&lt;/li&gt;
&lt;li&gt;TypeScript support&lt;/li&gt;
&lt;li&gt;Key-value storage API&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Use Cases&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Offline-first applications&lt;/li&gt;
&lt;li&gt;Local data caching&lt;/li&gt;
&lt;li&gt;Complex local queries&lt;/li&gt;
&lt;li&gt;Structured data storage&lt;/li&gt;
&lt;li&gt;Migration from existing SQLite databases&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Integration Options&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;SQL query execution&lt;/li&gt;
&lt;li&gt;Prepared statements&lt;/li&gt;
&lt;li&gt;Database migrations&lt;/li&gt;
&lt;li&gt;Key-value storage mode&lt;/li&gt;
&lt;li&gt;React hooks integration with SQLiteProvider&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Choose SQLite when you need:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Complete control over your data structure&lt;/li&gt;
&lt;li&gt;Complex local queries&lt;/li&gt;
&lt;li&gt;Familiar SQL syntax&lt;/li&gt;
&lt;li&gt;Proven reliability&lt;/li&gt;
&lt;li&gt;Small app size&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Essential Developer Tools&lt;/h2&gt;
&lt;h3&gt;Testing Tools&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Maestro&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Maestro for UI testing:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Easy setup&lt;/li&gt;
&lt;li&gt;Reliable UI testing&lt;/li&gt;
&lt;li&gt;Great developer experience&lt;/li&gt;
&lt;/ul&gt;
&lt;ol start=&quot;2&quot;&gt;
&lt;li&gt;&lt;strong&gt;React Native Testing Library&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;React Native Testing Library:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Industry standard for unit testing&lt;/li&gt;
&lt;li&gt;Comprehensive documentation&lt;/li&gt;
&lt;li&gt;Large community support&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Monitoring and Debugging&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Sentry&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Sentry for production monitoring:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Real-time error tracking&lt;/li&gt;
&lt;li&gt;Performance monitoring&lt;/li&gt;
&lt;li&gt;Crash reporting&lt;/li&gt;
&lt;li&gt;Debug information&lt;/li&gt;
&lt;/ul&gt;
&lt;ol start=&quot;2&quot;&gt;
&lt;li&gt;&lt;strong&gt;Reactotron&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Reactotron for development debugging:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;API monitoring&lt;/li&gt;
&lt;li&gt;State management debugging&lt;/li&gt;
&lt;li&gt;Performance tracking&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;CI/CD Solutions&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Expo EAS (Expo Application Services)&lt;/strong&gt;
EAS provides:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Cloud builds&lt;/li&gt;
&lt;li&gt;Automatic app submission&lt;/li&gt;
&lt;li&gt;Over-the-air updates&lt;/li&gt;
&lt;li&gt;Workflow automation&lt;/li&gt;
&lt;li&gt;Seamless integration with Expo projects&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These tools form a robust development environment that can significantly improve your React Native development workflow. The combination of these solutions provides a comprehensive setup for building, testing, and deploying professional React Native applications.&lt;/p&gt;
&lt;h2&gt;Essential Utility Packages&lt;/h2&gt;
&lt;p&gt;These packages are considered must-haves for specific functionalities in React Native development:&lt;/p&gt;
&lt;h3&gt;Storage and Performance&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;React Native MMKV&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;MMKV for high-performance storage:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Fastest key-value storage available&lt;/li&gt;
&lt;li&gt;Native implementation&lt;/li&gt;
&lt;li&gt;Perfect alternative to AsyncStorage&lt;/li&gt;
&lt;li&gt;Minimal setup required&lt;/li&gt;
&lt;/ul&gt;
&lt;ol start=&quot;2&quot;&gt;
&lt;li&gt;&lt;strong&gt;FlashList&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;FlashList for optimized list rendering:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Drop-in replacement for FlatList&lt;/li&gt;
&lt;li&gt;Significantly better performance&lt;/li&gt;
&lt;li&gt;Similar API to FlatList&lt;/li&gt;
&lt;li&gt;Built-in recycling system&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Form Management&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;React Hook Form&lt;/strong&gt;
React Hook Form with Zod for form handling:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Performant form validation&lt;/li&gt;
&lt;li&gt;Type-safe with Zod integration&lt;/li&gt;
&lt;li&gt;Minimal re-renders&lt;/li&gt;
&lt;li&gt;Great React Native support&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Image Management&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Expo Image&lt;/strong&gt;
Expo Image for optimized image handling:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Built-in caching&lt;/li&gt;
&lt;li&gt;Memory management&lt;/li&gt;
&lt;li&gt;Progressive loading&lt;/li&gt;
&lt;li&gt;Cross-platform optimization&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;UI Interactions&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Zego&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Zego for advanced UI interactions:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Beautiful dropdown menus&lt;/li&gt;
&lt;li&gt;Context menus&lt;/li&gt;
&lt;li&gt;Force touch overlays&lt;/li&gt;
&lt;li&gt;Native feel&lt;/li&gt;
&lt;/ul&gt;
&lt;ol start=&quot;2&quot;&gt;
&lt;li&gt;&lt;strong&gt;React Native Gesture Handler&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Gesture Handler for native-powered gestures:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Pan gestures&lt;/li&gt;
&lt;li&gt;Long press&lt;/li&gt;
&lt;li&gt;Rotation&lt;/li&gt;
&lt;li&gt;Fling gestures&lt;/li&gt;
&lt;li&gt;Built-in Expo support&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Authentication and Monetization&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Clerk&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Clerk for comprehensive auth management:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Complete user management&lt;/li&gt;
&lt;li&gt;Social provider integration&lt;/li&gt;
&lt;li&gt;Security best practices&lt;/li&gt;
&lt;li&gt;Easy implementation&lt;/li&gt;
&lt;/ul&gt;
&lt;ol start=&quot;2&quot;&gt;
&lt;li&gt;&lt;strong&gt;RevenueCat&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;RevenueCat for in-app purchases:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Cross-platform purchase management&lt;/li&gt;
&lt;li&gt;Easy product sync&lt;/li&gt;
&lt;li&gt;Analytics and insights&lt;/li&gt;
&lt;li&gt;Simplified implementation&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Camera Integration&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;React Native Vision Camera&lt;/strong&gt;
Vision Camera for advanced camera features:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;High-performance camera access&lt;/li&gt;
&lt;li&gt;Photo and video capture&lt;/li&gt;
&lt;li&gt;QR code scanning&lt;/li&gt;
&lt;li&gt;Barcode recognition&lt;/li&gt;
&lt;li&gt;Native implementation&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;The React Native ecosystem in 2025 is more mature and robust than ever. While the UI landscape might continue to evolve, the core tools and utilities have stabilized, providing a solid foundation for building professional mobile applications. This tech stack represents the best-in-class solutions for various development needs, backed by strong communities and proven in production environments.&lt;/p&gt;
&lt;p&gt;The combination of these tools enables developers to create high-performance, maintainable, and feature-rich applications while maintaining excellent developer experience. As the React Native ecosystem continues to grow, these recommendations will help you make informed decisions for your next mobile project.&lt;/p&gt;
]]></content:encoded>
            <dc:creator>Rami Chabchoub</dc:creator>
        </item>
        <item>
            <title><![CDATA[React Query Data Transformations]]></title>
            <description><![CDATA[How to transform data in React Query]]></description>
            <link>https://www.ramicode.com/en/articles/react-query-data-transformations</link>
            <guid isPermaLink="false">react-query-data-transformations</guid>
            <dc:creator><![CDATA[Rami Chabchoub]]></dc:creator>
            <pubDate>Fri, 17 Jan 2025 00:00:00 GMT</pubDate>
            <content:encoded><![CDATA[&lt;p&gt;Welcome to Part 2 of &amp;quot;Things I have to say about react-query&amp;quot;.
As I&amp;#39;ve become more and more involved with the library and the community around it, I&amp;#39;ve observed some more patterns people frequently ask about.
Initially, I wanted to write them all down in one big article, but then decided to break them down into more manageable pieces.
The first one is about a quite common and important task: Data Transformation.&lt;/p&gt;
&lt;h1&gt;Data Transformation&lt;/h1&gt;
&lt;p&gt;Let&amp;#39;s face it - most of us are not using GraphQL.
If you do, then you can be very happy because you have the luxury of requesting your data in the format that you desire.&lt;/p&gt;
&lt;p&gt;If you are working with REST though, you are constrained by what the backend returns.
So how and where do you best transform data when working with react-query?
The only answer worth a damn in software development applies here as well:&lt;/p&gt;

It depends.


&lt;p&gt;Here are 3+1 approaches on where you can transform data with their respective pros and cons:&lt;/p&gt;
&lt;h2&gt;0. On the backend&lt;/h2&gt;
&lt;p&gt;This is my favourite approach, if you can afford it.
If the backend returns data in exactly the structure we want, there is nothing we need to do.
While this might sound unrealistic in many cases, e.g. when working with public REST APIs, it is also quite possible to achieve in enterprise applications.
If you are in control of the backend and have an endpoint that returns data for your exact use-case, prefer to deliver the data the way you expect it.&lt;/p&gt;
&lt;p&gt;🟢   no work on the frontend&lt;/p&gt;
&lt;p&gt;🔴   not always possible&lt;/p&gt;
&lt;h2&gt;1. In the queryFn&lt;/h2&gt;
&lt;p&gt;The queryFn is the function that you pass to useQuery.
It expects you to return a Promise, and the resulting data winds up in the query cache.
But it doesn&amp;#39;t mean that you have to absolutely return data in the structure that the backend delivers here.
You can transform it before doing so:&lt;/p&gt;

```typescript showLineNumbers
const fetchTodos = async (): Promise =&gt; {
  const response = await axios.get(&apos;todos&apos;)
  const data: Todos = response.data

&lt;p&gt;  return data.map((todo) =&amp;gt; todo.name.toUpperCase())
}&lt;/p&gt;
&lt;p&gt;export const useTodosQuery = () =&amp;gt;
  useQuery({
    queryKey: [&amp;#39;todos&amp;#39;],
    queryFn: fetchTodos,
  })&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;/CodeBlock&amp;gt;

On the frontend, you can then work with this data &amp;quot;as if it came like this from the backend&amp;quot;.
No where in your code will you actually work with todo names that are not upper-cased.
You will also not have access to the original structure.
If you look at the react-query-devtools, you will see the transformed structure.
If you look at the network trace, you&amp;#39;ll see the original structure.
This might be confusing, so keep that in mind.

Also, there is no optimization that react-query can do for you here.
Every time a fetch is executed, your transformation will run.
If it&amp;#39;s expensive, consider one of the other alternatives.
Some companies also have a shared api layer that abstracts data fetching, so you might not have access to this layer to do your transformations.

🟢   very &amp;quot;close to the backend&amp;quot; in terms of co-location

🟡   the transformed structure winds up in the cache, so you don&amp;#39;t have access to the original structure

🔴   runs on every fetch

🔴   not feasible if you have a shared api layer that you cannot freely modify

## 2. In the render function
As advised in &amp;lt;A href=&amp;quot;https://tkdodo.eu/blog/practical-react-query&amp;quot;&amp;gt;Part 1&amp;lt;/A&amp;gt;, if you create custom hooks, you can easily do transformations there:

&amp;lt;CodeBlock title=&amp;quot;custom-hook-transformation&amp;quot;&amp;gt;
```typescript showLineNumbers {12-15}
const fetchTodos = async (): Promise&amp;lt;Todos&amp;gt; =&amp;gt; {
  const response = await axios.get(&amp;#39;todos&amp;#39;)
  return response.data
}

export const useTodosQuery = () =&amp;gt; {
  const queryInfo = useQuery({
    queryKey: [&amp;#39;todos&amp;#39;],
    queryFn: fetchTodos,
  })

  return {
    ...queryInfo,
    data: queryInfo.data?.map((todo) =&amp;gt; todo.name.toUpperCase()),
  }
}
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;As it stands, this will not only run every time your fetch function runs, but actually on every render (even those that do not involve data fetching).
This is likely not a problem at all, but if it is, you can optimize with useMemo.
Be careful to define your dependencies as narrow as possible.
data inside the queryInfo will be referentially stable unless something really changed (in which case you want to recompute your transformation), but the queryInfo itself will not.
If you add queryInfo as your dependency, the transformation will again run on every render:&lt;/p&gt;

```typescript showLineNumbers
export const useTodosQuery = () =&gt; {
  const queryInfo = useQuery({
    queryKey: [&apos;todos&apos;],
    queryFn: fetchTodos
  })

&lt;p&gt;  return {
    ...queryInfo,
    // 🚨 don&amp;#39;t do this - the useMemo does nothing at all here!
    data: React.useMemo(
      () =&amp;gt; queryInfo.data?.map((todo) =&amp;gt; todo.name.toUpperCase()),
      [queryInfo]
    ),&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// ✅ correctly memoizes by queryInfo.data
data: React.useMemo(
  () =&amp;gt; queryInfo.data?.map((todo) =&amp;gt; todo.name.toUpperCase()),
  [queryInfo.data]
),
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;  }
}&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;/CodeBlock&amp;gt;

Especially if you have additional logic in your custom hook to combine with your data transformation, this is a good option. Be aware that data can be potentially undefined, so use optional chaining when working with it.

&amp;lt;Update&amp;gt;
Since React Query has tracked queries turned on per default since v4, spreading ...queryInfo is no longer recommended, because it invokes getters on all properties.
&amp;lt;/Update&amp;gt;

🟢   optimizable via useMemo

🟡   exact structure cannot be inspected in the devtools

🔴   a bit more convoluted syntax

🔴   data can be potentially undefined

🔴   not recommended with tracked queries

## 3. using the select option
v3 introduced built-in selectors, which can also be used to transform data:

&amp;lt;CodeBlock title=&amp;quot;select-transformation&amp;quot;&amp;gt;
```typescript showLineNumbers {5}
export const useTodosQuery = () =&amp;gt;
  useQuery({
    queryKey: [&amp;#39;todos&amp;#39;],
    queryFn: fetchTodos,
    select: (data) =&amp;gt; data.map((todo) =&amp;gt; todo.name.toUpperCase()),
  })
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;selectors will only be called if data exists, so you don&amp;#39;t have to care about undefined here.
Selectors like the one above will also run on every render, because the functional identity changes (it&amp;#39;s an inline function).
If your transformation is expensive, you can memoize it either with useCallback, or by extracting it to a stable function reference:&lt;/p&gt;

```typescript showLineNumbers {8,9, 16-20}
const transformTodoNames = (data: Todos) =&gt;
  data.map((todo) =&gt; todo.name.toUpperCase())

&lt;p&gt;export const useTodosQuery = () =&amp;gt;
  useQuery({
    queryKey: [&amp;#39;todos&amp;#39;],
    queryFn: fetchTodos,
    // ✅ uses a stable function reference
    select: transformTodoNames,
  })&lt;/p&gt;
&lt;p&gt;export const useTodosQuery = () =&amp;gt;
  useQuery({
    queryKey: [&amp;#39;todos&amp;#39;],
    queryFn: fetchTodos,
    // ✅ memoizes with useCallback
    select: React.useCallback(
      (data: Todos) =&amp;gt; data.map((todo) =&amp;gt; todo.name.toUpperCase()),
      []
    ),
  })&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;/CodeBlock&amp;gt;

Further, the select option can also be used to subscribe to only parts of the data.
This is what makes this approach truly unique. Consider the following example:

&amp;lt;CodeBlock title=&amp;quot;select-partial-subscriptions&amp;quot;&amp;gt;
```javascript showLineNumbers
export const useTodosQuery = (select) =&amp;gt;
  useQuery({
    queryKey: [&amp;#39;todos&amp;#39;],
    queryFn: fetchTodos,
    select,
  })

export const useTodosCount = () =&amp;gt;
  useTodosQuery((data) =&amp;gt; data.length)
export const useTodo = (id) =&amp;gt;
  useTodosQuery((data) =&amp;gt; data.find((todo) =&amp;gt; todo.id === id))
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;Here, we&amp;#39;ve created a useSelector like API by passing a custom selector to our useTodosQuery.
The custom hooks still works like before, as select will be undefined if you don&amp;#39;t pass it, so the whole state will be returned.&lt;/p&gt;
&lt;p&gt;But if you pass a selector, you are now only subscribed to the result of the selector function.
This is quite powerful, because it means that even if we update the name of a todo, our component that only subscribes to the count via useTodosCount will not rerender.
The count hasn&amp;#39;t changed, so react-query can choose to not inform this observer about the update 🥳 (Please note that this is a bit simplified here and technically not entirely true - I will talk in more detail about render optimizations in Part 3).&lt;/p&gt;
&lt;p&gt;🟢   best optimizations&lt;/p&gt;
&lt;p&gt;🟢   allows for partial subscriptions&lt;/p&gt;
&lt;p&gt;🟡   structure can be different for every observer&lt;/p&gt;
&lt;p&gt;🟡   structural sharing is performed twice (I will also talk about this in more detail in Part 3)&lt;/p&gt;
&lt;p&gt;That&amp;#39;s all I have for today 👋.&lt;/p&gt;
]]></content:encoded>
            <dc:creator>Rami Chabchoub</dc:creator>
        </item>
        <item>
            <title><![CDATA[React Query Render Optimizations]]></title>
            <description><![CDATA[How to optimize React Query render]]></description>
            <link>https://www.ramicode.com/en/articles/react-query-render-optimizations</link>
            <guid isPermaLink="false">react-query-render-optimizations</guid>
            <dc:creator><![CDATA[Rami Chabchoub]]></dc:creator>
            <pubDate>Sat, 18 Jan 2025 00:00:00 GMT</pubDate>
            <content:encoded><![CDATA[
Render optimizations are an advanced concept for any app.
React Query already comes with very good optimizations and defaults out of the box, and most of the time, no further optimizations are needed.
&quot;Unneeded re-renders&quot; is a topic that many people tend to put a lot of focus on, which is why I&apos;ve decided to cover it.
But I wanted to point out once again, that usually, for most apps, render optimizations probably don&apos;t matter as much as you&apos;d think.
Re-renders are a good thing.
They make sure your app is up-to-date.
I&apos;d take an &quot;unnecessary re-render&quot; over a &quot;missing render-that-should-have-been-there&quot; all day every day.
For more on this topic, please read:
* Fix the slow render before you fix the re-render by Kent C. Dodds
* this article by @ryanflorence about premature optimizations


&lt;p&gt;I&amp;#39;ve already written quite a bit about render optimizations when describing the select option in #2: React Query Data Transformations.
However, &amp;quot;Why does React Query re-render my component two times even though nothing changed in my data&amp;quot; is the question I probably needed to answer the most (apart from maybe: &amp;quot;Where can I find the v2 docs&amp;quot; 😅).
So let me try to explain it in-depth.&lt;/p&gt;
&lt;h1&gt;isFetching transition&lt;/h1&gt;
&lt;p&gt;I haven&amp;#39;t been entirely honest in the last example when I said that this component will only re-render if the length of todos change:&lt;/p&gt;

```typescript showLineNumbers
export const useTodosQuery = (select) =&gt;
  useQuery({
    queryKey: [&apos;todos&apos;],
    queryFn: fetchTodos,
    select,
  })
export const useTodosCount = () =&gt;
  useTodosQuery((data) =&gt; data.length)

&lt;p&gt;function TodosCount() {
  const todosCount = useTodosCount()&lt;/p&gt;
&lt;p&gt;  return &lt;div&gt;{todosCount.data}&lt;/div&gt;
}&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;/CodeBlock&amp;gt;

Every time you make a background refetch, this component will re-render twice with the following query info:

```bash
{ status: &amp;#39;success&amp;#39;, data: 2, isFetching: true }
{ status: &amp;#39;success&amp;#39;, data: 2, isFetching: false }
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That is because React Query exposes a lot of meta information for each query, and isFetching is one of them.
This flag will always be true when a request is in-flight.
This is quite useful if you want to display a background loading indicator.
But it&amp;#39;s also kinda unnecessary if you don&amp;#39;t do that.&lt;/p&gt;
&lt;h1&gt;notifyOnChangeProps&lt;/h1&gt;
&lt;p&gt;For this use-case, React Query has the &lt;code&gt;notifyOnChangeProps&lt;/code&gt; option.
It can be set on a per-observer level to tell React Query: Please only inform this observer about changes if one of these props change.
By setting this option to &lt;code&gt;[&amp;#39;data&amp;#39;]&lt;/code&gt;, we will find the optimized version we seek:&lt;/p&gt;

```typescript showLineNumbers {1, 6, 9}
export const useTodosQuery = (select, notifyOnChangeProps) =&gt;
  useQuery({
    queryKey: [&apos;todos&apos;],
    queryFn: fetchTodos,
    select,
    notifyOnChangeProps,
  })
export const useTodosCount = () =&gt;
  useTodosQuery((data) =&gt; data.length, [&apos;data&apos;])
```


&lt;p&gt;You can see this in action in the optimistic-updates-typescript example in the docs.&lt;/p&gt;
&lt;h1&gt;Staying in sync&lt;/h1&gt;
&lt;p&gt;While the above code works well, it can get out of sync quite easily.
What if we want to react to the error, too?
Or we start to use the isLoading flag?
We have to keep the notifyOnChangeProps list in sync with whichever fields we are actually using in our components.
If we forget to do that, and we only observe the data property, but get an error that we also display, our component will not re-render and is thus outdated.
This is especially troublesome if we hard-code this in our custom hook, because the hook does not know what the component will actually use:&lt;/p&gt;

```typescript showLineNumbers
export const useTodosCount = () =&gt;
  useTodosQuery((data) =&gt; data.length, [&apos;data&apos;])

&lt;p&gt;function TodosCount() {
  // 🚨 we are using error,
  // but we are not getting notified if error changes!
  const { error, data } = useTodosCount()&lt;/p&gt;
&lt;p&gt;  return (
    &lt;div&gt;
      {error ? error : null}
      {data ? data : null}
    &lt;/div&gt;
  )
}&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;/CodeBlock&amp;gt;

As I have hinted in the disclaimer in the beginning, I think this is way worse than the occasional unneeded re-render.
Of course, we can pass the option to the custom hook, but this still feels quite manual and boilerplate-y.
Is there a way to do this automatically? Turns out, there is:

# Tracked Queries
I&amp;#39;m quite proud of this feature, given that it was my first major contribution to the library.
If you set `notifyOnChangeProps` to `&amp;#39;tracked&amp;#39;`, React Query will keep track of the fields you are using during render, and will use this to compute the list.
This will optimize exactly the same way as specifying the list manually, except that you don&amp;#39;t have to think about it.
You can also turn this on globally for all your queries:

&amp;lt;CodeBlock title=&amp;quot;tracked-queries&amp;quot;&amp;gt;
```typescript showLineNumbers
const queryClient = new QueryClient({
  defaultOptions: {
    queries: {
      notifyOnChangeProps: &amp;#39;tracked&amp;#39;,
    },
  },
})
function App() {
  return (
    &amp;lt;QueryClientProvider client={queryClient}&amp;gt;
      &amp;lt;Example /&amp;gt;
    &amp;lt;/QueryClientProvider&amp;gt;
  )
}
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;With this, you never have to think about re-renders again.
Of course, tracking the usages has a bit of an overhead as well, so make sure you use this wisely.
There are also some limitations to tracked queries, which is why this is an opt-in feature:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;If you use object rest destructuring, you are effectively observing all fields.
Normal destructuring is fine, just don&amp;#39;t do this:&lt;/li&gt;
&lt;/ul&gt;

```typescript showLineNumbers
// 🚨 will track all fields
const { isLoading, ...queryInfo } = useQuery(...)

&lt;p&gt;// ✅ this is totally fine
const { isLoading, data } = useQuery(...)&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;/CodeBlock&amp;gt;

* Tracked queries only work &amp;quot;during render&amp;quot;.
If you only access fields during effects, they will not be tracked.
This is quite the edge case though because of dependency arrays:

&amp;lt;CodeBlock title=&amp;quot;tracking-effects&amp;quot;&amp;gt;
```typescript showLineNumbers
const queryInfo = useQuery(...)

// 🚨 will not corectly track data
React.useEffect(() =&amp;gt; {
    console.log(queryInfo.data)
})

// ✅ fine because the dependency array is accessed during render
React.useEffect(() =&amp;gt; {
    console.log(queryInfo.data)
}, [queryInfo.data])
&lt;/code&gt;&lt;/pre&gt;


&lt;ul&gt;
&lt;li&gt;Tracked queries don&amp;#39;t reset on each render, so if you track a field once, you&amp;#39;ll track it for the lifetime of the observer:&lt;/li&gt;
&lt;/ul&gt;

```typescript showLineNumbers
const queryInfo = useQuery(...)

&lt;p&gt;if (someCondition()) {
    // 🟡 we will track the data field if someCondition was true in any previous render cycle
    return &lt;div&gt;{queryInfo.data}&lt;/div&gt;
}&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;/CodeBlock&amp;gt;

&amp;lt;Update&amp;gt;
Starting with v4, tracked queries are turned on per default in React Query, and you can opt out of the feature with `notifyOnChangeProps: &amp;#39;all&amp;#39;`.
&amp;lt;/Update&amp;gt;

# Structural sharing
A different, but no less important render optimization that React Query has turned on out of the box is structural sharing.
This feature makes sure that we keep referential identity of our `data` on every level.
As an example, suppose you have the following data structure:

&amp;lt;CodeBlock&amp;gt;
```json showLineNumbers
[
  { &amp;quot;id&amp;quot;: 1, &amp;quot;name&amp;quot;: &amp;quot;Learn React&amp;quot;, &amp;quot;status&amp;quot;: &amp;quot;active&amp;quot; },
  { &amp;quot;id&amp;quot;: 2, &amp;quot;name&amp;quot;: &amp;quot;Learn React Query&amp;quot;, &amp;quot;status&amp;quot;: &amp;quot;todo&amp;quot; }
]
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;Now suppose we transition our first todo into the done state, and we make a background refetch.
We&amp;#39;ll get a completely new json from our backend:&lt;/p&gt;

```diff showLineNumbers
[
-  { &quot;id&quot;: 1, &quot;name&quot;: &quot;Learn React&quot;, &quot;status&quot;: &quot;active&quot; },
+  { &quot;id&quot;: 1, &quot;name&quot;: &quot;Learn React&quot;, &quot;status&quot;: &quot;done&quot; },
   { &quot;id&quot;: 2, &quot;name&quot;: &quot;Learn React Query&quot;, &quot;status&quot;: &quot;todo&quot; }
]
```


&lt;p&gt;Now React Query will attempt to compare the old state and the new and keep as much of the previous state as possible.
In our example, the todos array will be new, because we updated a todo.
The object with id 1 will also be new, but the object for id 2 will be the same reference as the one in the previous state - React Query will just copy it over to the new result because nothing has changed in it.&lt;/p&gt;
&lt;p&gt;This comes in very handy when using selectors for partial subscriptions:&lt;/p&gt;

```typescript showLineNumbers
// ✅ will only re-render if _something_ within todo with id:2 changes
// thanks to structural sharing
const { data } = useTodo(2)
```


&lt;p&gt;As I&amp;#39;ve hinted before, for selectors, structural sharing will be done twice:
Once on the result returned from the queryFn to determine if anything changed at all, and then once more on the result of the selector function.
In some instances, especially when having very large datasets, structural sharing can be a bottleneck.
It also only works on json-serializable data.
If you don&amp;#39;t need this optimization, you can turn it off by setting structuralSharing: false on any query.&lt;/p&gt;
&lt;p&gt;Have a look at the replaceEqualDeep tests if you want to learn more about what happens under the hood.&lt;/p&gt;
]]></content:encoded>
            <dc:creator>Rami Chabchoub</dc:creator>
        </item>
        <item>
            <title><![CDATA[Status Checks in React Query]]></title>
            <description><![CDATA[How to use status checks in React Query]]></description>
            <link>https://www.ramicode.com/en/articles/status-checks-in-react-query</link>
            <guid isPermaLink="false">status-checks-in-react-query</guid>
            <dc:creator><![CDATA[Rami Chabchoub]]></dc:creator>
            <pubDate>Sun, 19 Jan 2025 00:00:00 GMT</pubDate>
            <content:encoded><![CDATA[&lt;p&gt;One advantage of React Query is the easy access to status fields of the query.
You instantly know if your query is loading or if it&amp;#39;s erroneous.
For this, the library exposes a bunch of boolean flags, which are mostly derived from the internal state machine.
Looking at the types, your query can be in one of the following states:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;success&lt;/code&gt;: Your query was successful, and you have &lt;code&gt;data&lt;/code&gt; for it&lt;/li&gt;
&lt;li&gt;&lt;code&gt;error&lt;/code&gt;: Your query did not work, and an &lt;code&gt;error&lt;/code&gt; is set&lt;/li&gt;
&lt;li&gt;&lt;code&gt;pending&lt;/code&gt;: Your query has no data&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Note that the &lt;code&gt;isFetching&lt;/code&gt; flag is not part of the internal state machine - it is an additional flag that will be true whenever a request is in-flight.
You can be fetching and success, you can be fetching and error - but you cannot be loading and success at the same time.
The state machine makes sure of that.&lt;/p&gt;


&lt;p&gt;Before v5, &lt;code&gt;pending&lt;/code&gt; was named &lt;code&gt;loading&lt;/code&gt;, and before v4, there was a fourth state called &lt;code&gt;idle&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Also, the &lt;code&gt;isFetching&lt;/code&gt; flag is derived from a secondary &lt;code&gt;fetchStatus&lt;/code&gt; - just like the &lt;code&gt;isPaused&lt;/code&gt; flag.
You can read more about this in #13: Offline React Query.
&lt;/p&gt;
&lt;h1&gt;The standard example&lt;/h1&gt;
&lt;p&gt;Most examples look something like this:&lt;/p&gt;

```typescript showLineNumbers
const todos = useTodos()

&lt;p&gt;if (todos.isPending) {
  return &amp;#39;Loading...&amp;#39;
}
if (todos.error) {
  return &amp;#39;An error has occurred: &amp;#39; + todos.error.message
}&lt;/p&gt;
&lt;p&gt;return &lt;div&gt;{todos.data.map(renderTodo)}&lt;/div&gt; &lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;/CodeBlock&amp;gt;

Here, we check for pending and error first, and then display our data.
This is probably fine for some use-cases, but not for others.
Many data fetching solutions, especially hand-crafted ones, have no refetch mechanism, or only refetch on explicit user interactions.

But React Query does.

It refetches quite aggressively per default, and does so without the user actively requesting a refetch.
The concepts of `refetchOnMount`, `refetchOnWindowFocus` and `refetchOnReconnect` are great for keeping your data accurate, but they might cause a confusing ux if such an automatic background refetch fails.

# Background errors
In many situations, if a background refetch fails, it could be silently ignored.
But the code above does not do that. Let&amp;#39;s look at two examples:

* The user opens a page, and the initial query loads successfully.
They are working on the page for some time, then switch browser tabs to check emails.
They come back some minutes later, and React Query will do a background refetch. Now that fetch fails.
* Our user is on page with a list view, and they click on one item to drill down to the detail view.
This works fine, so they go back to the list view. Once they go to the detail view again, they will see data from the cache.
This is great - except if the background refetch fails.

In both situations, our query will be in the following state:

&amp;lt;CodeBlock&amp;gt;
```bash showLineNumbers
{
  &amp;quot;status&amp;quot;: &amp;quot;error&amp;quot;,
  &amp;quot;error&amp;quot;: { &amp;quot;message&amp;quot;: &amp;quot;Something went wrong&amp;quot; },
  &amp;quot;data&amp;quot;: [{ ... }]
}
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;As you can see, we will have both an error and the stale data available.
This is what makes React Query great - it embraces the stale-while-revalidate caching mechanism, which means it will always give you data if it exists, even if it&amp;#39;s stale.&lt;/p&gt;
&lt;p&gt;Now it&amp;#39;s up to us to decide what we display.
Is it important to show the error? Is it enough to show the stale data only, if we have any? Should we show both, maybe with a little background error indicator?&lt;/p&gt;
&lt;p&gt;There is no clear answer to this question - it depends on your exact use-case.
However, given the two above examples, I think it would be a somewhat confusing user experience if data would be replaced with an error screen.&lt;/p&gt;
&lt;p&gt;This is even more relevant when we take into account that React Query will retry failed queries three times per default with exponential backoff, so it might take a couple of seconds until the stale data is replaced with the error screen.
If you also have no background fetching indicator, this can be really perplexing.&lt;/p&gt;
&lt;p&gt;This is why I usually check for data-availability first:&lt;/p&gt;

```typescript showLineNumbers
const todos = useTodos()

&lt;p&gt;if (todos.data) {
  return &lt;div&gt;{todos.data.map(renderTodo)}&lt;/div&gt;
}
if (todos.error) {
  return &amp;#39;An error has occurred: &amp;#39; + todos.error.message
}&lt;/p&gt;
&lt;p&gt;return &amp;#39;Loading...&amp;#39;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;/CodeBlock&amp;gt;

Again, there is no clear principle of what is right, as it is highly dependent on the use-case.
Everyone should be aware of the consequences that aggressive refetching has, and we have to structure our code accordingly rather than strictly following the simple todo-examples 😉.

Special thanks go to &amp;lt;A href=&amp;quot;https://github.com/boschni&amp;quot;&amp;gt;Niek Bosch&amp;lt;/A&amp;gt; who first highlighted to me why this pattern of status checking can be harmful in some situations.
&lt;/code&gt;&lt;/pre&gt;
]]></content:encoded>
            <dc:creator>Rami Chabchoub</dc:creator>
        </item>
        <item>
            <title><![CDATA[Testing React Query]]></title>
            <description><![CDATA[How to test React Query]]></description>
            <link>https://www.ramicode.com/en/articles/testing-react-query</link>
            <guid isPermaLink="false">testing-react-query</guid>
            <dc:creator><![CDATA[Rami Chabchoub]]></dc:creator>
            <pubDate>Mon, 20 Jan 2025 00:00:00 GMT</pubDate>
            <content:encoded><![CDATA[&lt;p&gt;Questions around the testing topic come up quite often together with React Query, so I&amp;#39;ll try to answer some of them here.
I think one reason for that is that testing &amp;quot;smart&amp;quot; components (also called container components) is not the easiest thing to do.
With the rise of hooks, this split has been largely deprecated.
It is now encouraged to consume hooks directly where you need them rather than doing a mostly arbitrary split and drill props down.&lt;/p&gt;
&lt;p&gt;I think this is generally a very good improvement for colocation and code readability, but we now have more components that consume dependencies outside of &amp;quot;just props&amp;quot;.&lt;/p&gt;
&lt;p&gt;They might &lt;code&gt;useContext&lt;/code&gt;. They might &lt;code&gt;useSelector&lt;/code&gt;. Or they might &lt;code&gt;useQuery&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Those components are technically no longer pure, because calling them in different environments leads to different results.
When testing them, you need to carefully setup those surrounding environments to get things working.&lt;/p&gt;
&lt;h1&gt;Mocking network requests&lt;/h1&gt;
&lt;p&gt;Since React Query is an async server state management library, your components will likely make requests to a backend.
When testing, this backend is not available to actually deliver data, and even if, you likely don&amp;#39;t want to make your tests dependent on that.&lt;/p&gt;
&lt;p&gt;There are tons of articles out there on how to mock data with jest.
You can mock your api client if you have one. You can mock fetch or axios directly.
I can only second what Kent C. Dodds has written in his article Stop mocking fetch:&lt;/p&gt;
&lt;p&gt;Use mock service worker by @ApiMocking&lt;/p&gt;
&lt;p&gt;It can be your single source of truth when it comes to mocking your apis:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;works in node for testing&lt;/li&gt;
&lt;li&gt;supports REST and GraphQL&lt;/li&gt;
&lt;li&gt;has a storybook addon so you can write stories for your components that &lt;code&gt;useQuery&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;works in the browser for development purposes, and you&amp;#39;ll still see the requests going out in the browser devtools&lt;/li&gt;
&lt;li&gt;works with cypress, similar to fixtures
With our network layer being taken care of, we can start talking about React Query specific things to keep an eye on:&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;QueryClientProvider&lt;/h1&gt;
&lt;p&gt;Whenever you use React Query, you need a QueryClientProvider and give it a queryClient - a vessel which holds the &lt;code&gt;QueryCache&lt;/code&gt;.
The cache will in turn hold the data of your queries.&lt;/p&gt;
&lt;p&gt;I prefer to give each test its own QueryClientProvider and create a &lt;code&gt;new QueryClient&lt;/code&gt; for each test.
That way, tests are completely isolated from each other.
A different approach might be to clear the cache after each test, but I like to keep shared state between tests as minimal as possible.
Otherwise, you might get unexpected and flaky results if you run your tests in parallel.&lt;/p&gt;
&lt;p&gt;For custom hooks
If you are testing custom hooks, I&amp;#39;m quite certain you&amp;#39;re using react-hooks-testing-library.
It&amp;#39;s the easiest thing there is to test hooks.
With that library, we can wrap our hook in a wrapper, which is a React component to wrap the test component in when rendering.
I think this is the perfect place to create the QueryClient, because it will be executed once per test:&lt;/p&gt;

```typescript showLineNumbers
const createWrapper = () =&gt; {
  // ✅ creates a new QueryClient for each test
  const queryClient = new QueryClient()
  return ({ children }) =&gt; (
    
      {children}
    
  )
}

&lt;p&gt;test(&amp;#39;my first test&amp;#39;, async () =&amp;gt; {
  const { result } = renderHook(() =&amp;gt; useCustomHook(), {
    wrapper: createWrapper(),
  })
})&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;/CodeBlock&amp;gt;

# For components
If you want to test a Component that uses a `useQuery` hook, you also need to wrap that Component in QueryClientProvider.
A small wrapper around `render` from &amp;lt;A href=&amp;quot;https://testing-library.com/docs/react-testing-library/intro/&amp;quot;&amp;gt;react-testing-library&amp;lt;/A&amp;gt; seems like a good choice.
Have a look at how React Query does it &amp;lt;A href=&amp;quot;https://github.com/TanStack/query/blob/ead2e5dd5237f3d004b66316b5f36af718286d2d/src/react/tests/utils.tsx#L6-L17&amp;quot;&amp;gt;internally for their tests&amp;lt;/A&amp;gt;.

# Turn off retries
It&amp;#39;s one of the most common &amp;quot;gotchas&amp;quot; with React Query and testing: The library defaults to three retries with exponential backoff, which means that your tests are likely to timeout if you want to test an erroneous query.
The easiest way to turn retries off is, again, via the QueryClientProvider.
Let&amp;#39;s extend the above example:

&amp;lt;CodeBlock title=&amp;quot;no-retries&amp;quot;&amp;gt;
```typescript showLineNumbers {2-9}
const createWrapper = () =&amp;gt; {
  const queryClient = new QueryClient({
    defaultOptions: {
      queries: {
        // ✅ turns retries off
        retry: false,
      },
    },
  })

  return ({ children }) =&amp;gt; (
    &amp;lt;QueryClientProvider client={queryClient}&amp;gt;
      {children}
    &amp;lt;/QueryClientProvider&amp;gt;
  )
}

test(&amp;quot;my first test&amp;quot;, async () =&amp;gt; {
  const { result } = renderHook(() =&amp;gt; useCustomHook(), {
    wrapper: createWrapper()
  })
})
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;This will set the defaults for all queries in the component tree to &amp;quot;no retries&amp;quot;.
It is important to know that this will only work if your actual &lt;code&gt;useQuery&lt;/code&gt; has no explicit retries set.
If you have a query that wants 5 retries, this will still take precedence, because defaults are only taken as a fallback.&lt;/p&gt;
&lt;h1&gt;setQueryDefaults&lt;/h1&gt;
&lt;p&gt;The best advice I can give you for this problem is: Don&amp;#39;t set these options on &lt;code&gt;useQuery&lt;/code&gt; directly.
Try to use and override the defaults as much as possible, and if you really need to change something for specific queries, use queryClient.setQueryDefaults.&lt;/p&gt;
&lt;p&gt;So for example, instead of setting retry on &lt;code&gt;useQuery&lt;/code&gt;:&lt;/p&gt;

```typescript showLineNumbers
const queryClient = new QueryClient()

&lt;p&gt;function App() {
  return (
    
      
    
  )
}&lt;/p&gt;
&lt;p&gt;function Example() {
  // 🚨 you cannot override this setting for tests!
  const queryInfo = useQuery({
    queryKey: [&amp;#39;todos&amp;#39;],
    queryFn: fetchTodos,
    retry: 5,
  })
}&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;/CodeBlock&amp;gt;

Set it like this:

&amp;lt;CodeBlock title=&amp;quot;setQueryDefaults&amp;quot;&amp;gt;
```typescript showLineNumbers {9,10}
const queryClient = new QueryClient({
  defaultOptions: {
    queries: {
      retry: 2,
    },
  },
})

// ✅ only todos will retry 5 times
queryClient.setQueryDefaults([&amp;#39;todos&amp;#39;], { retry: 5 })

function App() {
  return (
    &amp;lt;QueryClientProvider client={queryClient}&amp;gt;
      &amp;lt;Example /&amp;gt;
    &amp;lt;/QueryClientProvider&amp;gt;
  )
}
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;Here, all queries will retry two times, only todos will retry five times, and I still have the option to turn it off for all queries in my tests 🙌.&lt;/p&gt;
&lt;h1&gt;ReactQueryConfigProvider&lt;/h1&gt;
&lt;p&gt;Of course, this only works for known query keys.
Sometimes, you really want to set some configs on a subset of your component tree.
In v2, React Query had a ReactQueryConfigProvider for that exact use-case.
You can achieve the same thing in v3 with a couple of lines of codes:&lt;/p&gt;

```typescript showLineNumbers
const ReactQueryConfigProvider = ({ children, defaultOptions }) =&gt; {
  const client = useQueryClient()
  const [newClient] = React.useState(
    () =&gt;
      new QueryClient({
        queryCache: client.getQueryCache(),
        muationCache: client.getMutationCache(),
        defaultOptions,
      })
  )

&lt;p&gt;  return (
    
      {children}
    
  )
}&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;/CodeBlock&amp;gt;

You can see this in action in this &amp;lt;A href=&amp;quot;https://codesandbox.io/p/sandbox/react-query-config-provider-v3-lt00f&amp;quot;&amp;gt;codesandbox example&amp;lt;/A&amp;gt;.

# Always await the query
Since React Query is async by nature, when running the hook, you won&amp;#39;t immediately get a result.
It usually will be in loading state and without data to check.
The &amp;lt;A href=&amp;quot;https://react-hooks-testing-library.com/reference/api#async-utilities&amp;quot;&amp;gt;async utilities&amp;lt;/A&amp;gt; from react-hooks-testing-library offer a lot of ways to solve this problem.
For the simplest case, we can just wait until the query has transitioned to success state:

&amp;lt;CodeBlock title=&amp;quot;waitFor&amp;quot;&amp;gt;
```typescript showLineNumbers {21-24}
const createWrapper = () =&amp;gt; {
  const queryClient = new QueryClient({
    defaultOptions: {
      queries: {
        retry: false,
      },
    },
  })
  return ({ children }) =&amp;gt; (
    &amp;lt;QueryClientProvider client={queryClient}&amp;gt;
      {children}
    &amp;lt;/QueryClientProvider&amp;gt;
  )
}

test(&amp;quot;my first test&amp;quot;, async () =&amp;gt; {
  const { result, waitFor } = renderHook(() =&amp;gt; useCustomHook(), {
    wrapper: createWrapper()
  })

  // ✅ wait until the query has transitioned to success state
  await waitFor(() =&amp;gt; result.current.isSuccess)

  expect(result.current.data).toBeDefined()
}
&lt;/code&gt;&lt;/pre&gt;



@testing-library/react v13.1.0 also has a new renderHook that you can use.
However, it doesn&apos;t return its own `waitFor` util, so you&apos;ll have to use the one you can import from @testing-library/react instead.
The API is a bit different, as it doesn&apos;t allow to return a boolean, but expects a Promise instead.
That means we must adapt our code slightly:


```typescript showLineNumbers {8-11}
import { waitFor, renderHook } from &apos;@testing-library/react&apos;

&lt;p&gt;test(&amp;quot;my first test&amp;quot;, async () =&amp;gt; {
  const { result } = renderHook(() =&amp;gt; useCustomHook(), {
    wrapper: createWrapper()
  })&lt;/p&gt;
&lt;p&gt;  // ✅ return a Promise via expect to waitFor
  await waitFor(() =&amp;gt; expect(result.current.isSuccess).toBe(true))&lt;/p&gt;
&lt;p&gt;  expect(result.current.data).toBeDefined()
}&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;/CodeBlock&amp;gt;
&amp;lt;/Update&amp;gt;

# Putting it all together
I&amp;#39;ve set up a quick repository where all of this comes nicely together: mock-service-worker, react-testing-library and the mentioned wrapper.
It contains four tests - basic failure and success tests for custom hooks and components.
Have a look here: &amp;lt;A href=&amp;quot;https://github.com/TkDodo/testing-react-query&amp;quot;&amp;gt;https://github.com/TkDodo/testing-react-query&amp;lt;/A&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
]]></content:encoded>
            <dc:creator>Rami Chabchoub</dc:creator>
        </item>
    </channel>
</rss>