---
id: 67fe694ebcafe94ab7451a8f
title: Step 22
challengeType: 0
dashedName: step-22
---

# --description--

Your app works! Go ahead and test it out.

However, it's not as efficient as it could be. While React is already very performant, there are some cases where it can be better to cache the results of potentially expensive calculations, or to ensure that functions are not recreated on every render.

We'll improve the performance of your app over the following steps. But first, let's add some logging so you can see the lifecycle of this component more clearly.

Above `filteredItems`, add a `console.log()` statement that logs the string `Filtering items...` to the console.

# --hints--

You should add a `console.log()` statement above `filteredItems` that logs the string `Filtering items...` to the console.

```js
const script = [...document.querySelectorAll("script")].find((s) => s.dataset.src ===  "index.jsx").innerText;
const exports = {};
const a = eval(script);
const shoppingListString = exports.ShoppingList.toString();

assert.match(shoppingListString, /console\.log\s*\(\s*("|'|`)\s*Filtering\s+items\s*\.\.\.\s*("|'|`)\s*\);?/i);
```

# --seed--

## --seed-contents--

```html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Shopping List</title>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.3.1/umd/react.development.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.3.1/umd/react-dom.development.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/7.26.5/babel.min.js"></script>
    <script
      data-plugins="transform-modules-umd"
      type="text/babel"
      data-presets="react"
      data-type="module"
      src="index.jsx"
    ></script>
    <link rel="stylesheet" href="./styles.css" />
  </head>
  <body>
    <main id="app-container"></main>
    <script
      data-plugins="transform-modules-umd"
      type="text/babel"
      data-presets="react"
      data-type="module"
    >
      import { ShoppingList } from "./index.jsx";
      const appContainer = document.getElementById("app-container");
      const root = ReactDOM.createRoot(appContainer);
      root.render(<ShoppingList />);
    </script>
  </body>
</html>

```

```css
:root {
  --dark-grey: #1b1b32;
  --light-grey: #f5f6f7;
  --dark-orange: #f89808;
  --yellow: #f1be32;
  --golden-yellow: #feac32;
}

*,
*::before,
*::after {
  box-sizing: border-box;
}

body {
  font-family: Arial, sans-serif;
  line-height: 1.5;
  color: var(--dark-grey);
  background-color: var(--dark-grey);
}

main,
.container {
  display: flex;
  flex-direction: column;
  align-items: center;
}

.container {
  background-color: var(--light-grey);
  width: 90%;
  margin: 20px;
  padding: 10px;
}

h1 {
  color: var(--dark-grey);
}

form {
  text-align: center;
}

button {
  cursor: pointer;
}

button {
  cursor: pointer;
  width: 100px;
  margin: 3px;
  color: var(--dark-grey);
  background-color: var(--golden-yellow);
  background-image: linear-gradient(#fecc4c, #ffac33);
  border-color: var(--golden-yellow);
  border-width: 3px;
}

button:hover {
  background-image: linear-gradient(#ffcc4c, #f89808);
}

input {
  color: var(--dark-grey);
  margin-left: 5px;
  padding: 3px;
}

li {
  text-align: left;
  margin: 10px 0;
}

.selected-item {
  font-weight: bold;
}

@media (min-width: 425px) {
  .container {
    width: 400px;
  }
}

```

```jsx
const { useState } = React;

const items = [
  "Apples",
  "Bananas",
  "Strawberries",
  "Blueberries",
  "Mangoes",
  "Pineapple",
  "Lettuce",
  "Broccoli",
  "Paper Towels",
  "Dish Soap",
];

export const ShoppingList = () => {
  const [query, setQuery] = useState("");
  const [selectedItems, setSelectedItems] = useState([]);

  --fcc-editable-region--

  --fcc-editable-region--
  const filteredItems = items.filter((item) => 
    item.toLowerCase().includes(query.toLowerCase())
  );

  const toggleItem = (item) => {
    setSelectedItems((prev) =>
      prev.includes(item) ? prev.filter((i) => i !== item) : [...prev, item]
    );
  };

  return (
    <div className="container">
      <h1>Shopping List</h1>
      <form>
        <label htmlFor="search">Search for an item:</label>
        <input
          id="search"
          type="search"
          placeholder="Search..."
          aria-describedby="search-description"
          value={query}
          onChange={(e) => setQuery(e.target.value)}
        /> 
        <p id="search-description">Type to filter the list below:</p>
        <ul>
          {filteredItems.map((item) => {
            const isChecked = selectedItems.includes(item);
            return (
              <li
                key={item}
                style={{ textDecoration: isChecked ? "line-through" : "none" }}
              >
                <label>
                  <input
                    type="checkbox"
                    onChange={() => toggleItem(item)}
                    checked={isChecked}
                  />
                  {item}
                </label>
              </li>
            );
          })}
        </ul>
      </form>
    </div>
  );
};

```
