Creating our first Vue component - Learn web development

Creating our first Vue component
================================

* Previous
* Overview: Client-side JavaScript frameworks
* Next

Now it's time to dive deeper into Vue, and create our own custom component — we'll start by creating a component to represent each item in the todo list. Along the way, we'll learn about a few important concepts such as calling components inside other components, passing data to them via props, and saving data state.

**Note:** If you need to check your code against our version, you can find a finished version of the sample Vue app code in our todo-vue repository. For a running live version, see https://mdn.github.io/todo-vue/.

|  |  |
| --- | --- |
| Prerequisites: |
 Familiarity with the core HTML,
 CSS, and
 JavaScript languages,
 knowledge of the
 terminal/command line.

 Vue components are written as a combination of JavaScript objects that
 manage the app's data and an HTML-based template syntax that maps to
 the underlying DOM structure. For installation, and to use some of the
 more advanced features of Vue (like Single File Components or render
 functions), you'll need a terminal with
 Node
 and
 npm
 installed.
  |
| Objective: |
 To learn how to create a Vue component, render it inside another
 component, pass data into it using props, and save its state.
  |

Creating a ToDoItem component
-----------------------------

Let's create our first component, which will display a single todo item. We'll use this to build our list of todos.

1. In your `moz-todo-vue/src/components` directory, create a new file named `ToDoItem.vue`. Open the file in your code editor.
2. Create the component's template section by adding `<template></template>` to the top of the file.
3. Create a `<script></script>` section below your template section. Inside the `<script>` tags, add a default exported object `export default {}`, which is your component object.

Your file should now look like this:

```markup
<template></template>
<script>
export default {};
</script>
```

We can now begin to add actual content to our `ToDoItem`. Vue templates are currently only allowed a single root element — one element needs to wrap everything inside the template section (this will change when Vue 3 comes out). We'll use a `<div>` for that root element.

1. Add an empty `<div>` inside your component template now.
2. Inside that `<div>`, let's add a checkbox and a corresponding label. Add an `id` to the checkbox, and a `for` attribute mapping the checkbox to the label, as shown below.

```markup
<template>
  <div>
    <input type="checkbox" id="todo-item" />
    <label for="todo-item">My Todo Item</label>
  </div>
</template>
```

### Using TodoItem inside our app

This is all fine, but we haven't added the component to our app yet, so there's no way to test it and see if everything is working. Let's add it now.

1. Open up `App.vue` again.
2. At the top of your `<script>` tag, add the following to import your `ToDoItem` component:

```js
import ToDoItem from "./components/ToDoItem.vue";
```

3. Inside your component object, add the `components` property, and inside it add your `ToDoItem` component to register it.

Your `<script>` contents should now look like this:

```js
import ToDoItem from "./components/ToDoItem.vue";

export default {
  name: "app",
  components: {
    ToDoItem,
  },
};
```

This is the same way that the `HelloWorld` component was registered by the Vue CLI earlier.

 To actually render the `ToDoItem` component in the app, you need to go up into your `<template>` element and call it as a `<to-do-item></to-do-item>` element. Note that the component file name and its representation in JavaScript is in PascalCase (e.g. `ToDoList`), and the equivalent custom element is in kebab-case (e.g. `<to-do-list>`).
 It's necessary to use this casing style if you're writing Vue templates in the DOM directly

1. Underneath the `<h1>`, create an unordered list (`<ul>`) containing a single list item (`<li>`).
2. Inside the list item add `<to-do-item></to-do-item>`.

The `<template>` section of your `App.vue` file should now look something like this:

```markup
<div id="app">
  <h1>To-Do List</h1>
  <ul>
    <li>
      <to-do-item></to-do-item>
    </li>
  </ul>
</div>
```

If you check your rendered app again, you should now see your rendered `ToDoItem`, consisting of a checkbox and a label.

![The current rendering state of the app, which includes a title of To-Do List, and a single checkbox and label](/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Vue_first_component/rendered-todoitem.png)

Making components dynamic with props
------------------------------------

Our `ToDoItem` component is still not very useful because we can only really include this once on a page (IDs need to be unique), and we have no way to set the label text. Nothing about this is dynamic.

What we need is some component state. This can be achieved by adding props to our component. You can think of props as being similar to inputs in a function. The value of a prop gives components an initial state that affects their display.

### Registering props

In Vue, there are two ways to register props:

* The first way is to just list props out as an array of strings. Each entry in the array corresponds to the name of a prop.
* The second way is to define props as an object, with each key corresponding to the prop name. Listing props as an object allows you to specify default values, mark props as required, perform basic object typing (specifically around JavaScript primitive types), and perform simple prop validation.

**Note:** Prop validation only happens in development mode, so you can't strictly rely on it in production. Additionally, prop validation functions are invoked before the component instance is created, so they do not have access to the component state (or other props).

For this component, we'll use the object registration method.

1. Go back to your `ToDoItem.vue` file.
2. Add a `props` property inside the export `default {}` object, which contains an empty object.
3. Inside this object, add two properties with the keys `label` and `done`.
4. The `label` key's value should be an object with 2 properties (or **props**, as they are called in the context of being available to the components).
    1. The first is a `required` property, which will have a value of `true`. This will tell Vue that we expect every instance of this component to have a label field. Vue will warn us if a `ToDoItem` component does not have a label field.
    2. The second property we'll add is a `type` property. Set the value for this property as the JavaScript `String` type (note the capital "S"). This tells Vue that we expect the value of this property to be a string.
5. Now on to the `done` prop.
    1. First add a `default` field, with a value of `false`. This means that when no `done` prop is passed to a `ToDoItem` component, the `done` prop will have a value of false (bear in mind that this is not required — we only need `default` on non-required props).
    2. Next add a `type` field with a value of `Boolean`. This tells Vue we expect the value prop to be a JavaScript boolean type.

Your component object should now look like this:

```js
export default {
  props: {
    label: { required: true, type: String },
    done: { default: false, type: Boolean },
  },
};
```

### Using registered props

With these props defined inside the component object, we can now use these variable values inside our template. Let's start by adding the `label` prop to the component template.

In your `<template>`, replace the contents of the `<label>` element with `{{label}}`.

`{{}}` is a special template syntax in Vue, which lets us print the result of JavaScript expressions defined in our class, inside our template, including values and methods. It's important to know that content inside `{{}}` is displayed as text and not HTML. In this case, we're printing the value of the `label` prop.

Your component's template section should now look like this:

```markup
<template>
  <div>
    <input type="checkbox" id="todo-item" />
    <label for="todo-item">{{ label }}</label>
  </div>
</template>
```

Go back to your browser and you'll see the todo item rendered as before, but without a label (oh no!). Go to your browser's DevTools and you'll see a warning along these lines in the console:
```

[Vue warn]: Missing required prop: "label"

found in

---> <ToDoItem> at src/components/ToDoItem.vue
        <App> at src/App.vue
          <Root>
```

This is because we marked the `label` as a required prop, but we never gave the component that prop — we've defined where inside the template we want it used, but we haven't passed it into the component when calling it. Let's fix that.

Inside your `App.vue` file, add a `label` prop to the `<to-do-item></to-do-item>` component, just like a regular HTML attribute:

```markup
<to-do-item label="My ToDo Item"></to-do-item>
```

Now you'll see the label in your app, and the warning won't be spat out in the console again.

So that's props in a nutshell. Next we'll move on to how Vue persists data state.

Vue's data object
-----------------

If you change the value of the `label` prop passed into the `<to-do-item></to-do-item>` call in your `App` component, you should see it update. This is great. We have a checkbox, with an updatable label. However, we're currently not doing anything with the "done" prop — we can check the checkboxes in the UI, but nowhere in the app are we recording whether a todo item is actually done.

To achieve this, we want to bind the component's `done` prop to the `checked` attribute on the `<input>` element, so that it can serve as a record of whether the checkbox is checked or not. However, it's important that props serve as one-way data binding — a component should never alter the value of its own props. There are a lot of reasons for this. In part, components editing props can make debugging a challenge. If a value is passed to multiple children, it could be hard to track where the changes to that value were coming from. In addition, changing props can cause components to re-render. So mutating props in a component would trigger the component to rerender, which may in-turn trigger the mutation again.

To work around this, we can manage the `done` state using Vue's `data` property. The `data` property is where you can manage local state in a component, it lives inside the component object alongside the `props` property and has the following structure:

```js
data() {
  return {
    key: value
  }
}
```

You'll note that the `data` property is a function. This is to keep the data values unique for each instance of a component at runtime — the function is invoked separately for each component instance. If you declared data as just an object, all instances of that component would share the same values. This is a side-effect of the way Vue registers components and something you do not want.

You use `this` to access a component's props and other properties from inside data, as you may expect. We'll see an example of this shortly.

**Note:** Because of the way that `this` works in arrow functions (binding to the parent's context), you wouldn't be able to access any of the necessary attributes from inside `data` if you used an arrow function. So don't use an arrow function for the `data` property.

So let's add a `data` property to our `ToDoItem` component. This will return an object containing a single property that we'll call `isDone`, whose value is `this.done`.

Update the component object like so:

```js
export default {
  props: {
    label: { required: true, type: String },
    done: { default: false, type: Boolean },
  },
  data() {
    return {
      isDone: this.done,
    };
  },
};
```

Vue does a little magic here — it binds all of your props directly to the component instance, so we don't have to call `this.props.done`. It also binds other attributes (`data`, which you've already seen, and others like `methods`, `computed`, etc.) directly to the instance. This is, in part, to make them available to your template. The down-side to this is that you need to keep the keys unique across these attributes. This is why we called our `data` attribute `isDone` instead of `done`.

So now we need to attach the `isDone` property to our component. In a similar fashion to how Vue uses `{{}}` expressions to display JavaScript expressions inside templates, Vue has a special syntax to bind JavaScript expressions to HTML elements and components: **`v-bind`**. The `v-bind` expression looks like this:
```

v-bind:attribute="expression"
```

In other words, you prefix whatever attribute/prop you want to bind to with `v-bind:`. In most cases, you can use a shorthand for the `v-bind` property, which is to just prefix the attribute/prop with a colon. So `:attribute="expression"` works the same as `v-bind:attribute="expression"`.

So in the case of the checkbox in our `ToDoItem` component, we can use `v-bind` to map the `isDone` property to the `checked` attribute on the `<input>` element. Both of the following are equivalent:

```markup
<input type="checkbox" id="todo-item" v-bind:checked="isDone" />

<input type="checkbox" id="todo-item" :checked="isDone" />
```

You're free to use whichever pattern you would like. It's best to keep it consistent though. Because the shorthand syntax is more commonly used, this tutorial will stick to that pattern.

So let's do this. Update your `<input>` element now to include `:checked="isDone"`.

Test out your component by passing `:done="true"` to the `ToDoItem` call in `App.vue`. Note that you need to use the `v-bind` syntax, because otherwise `true` is passed as a string. The displayed checkbox should be checked.

```markup
<template>
  <div id="app">
    <h1>My To-Do List</h1>
    <ul>
      <li>
        <to-do-item label="My ToDo Item" :done="true"></to-do-item>
      </li>
    </ul>
  </div>
</template>
```

Try changing `true` to `false` and back again, reloading your app in between to see how the state changes.

Giving Todos a unique id
------------------------

Great! We now have a working checkbox where we can set the state programmatically. However, we can currently only add one `ToDoList` component to the page because the `id` is hardcoded. This would result in errors with assistive technology since the `id` is needed to correctly map labels to their checkboxes. To fix this, we can programmatically set the `id` in the component data.

We can use the lodash package's `uniqueid()` method to help keep the index unique. This package exports a function that takes in a string and appends a unique integer to the end of the prefix. This will be sufficient for keeping component `id`s unique.

Let's add the package to our project with npm; stop your server and enter the following command into your terminal:

```bash
npm install --save lodash.uniqueid
```

**Note:** If you prefer yarn, you could instead use `yarn add lodash.uniqueid`.

We can now import this package into our `ToDoItem` component. Add the following line at the top of `ToDoItem.vue`'s `<script>` element:

```js
import uniqueId from "lodash.uniqueid";
```

Next, add an `id` field to our data property, so the component object ends up looking like so (`uniqueId()` returns the specified prefix — `todo-` — with a unique string appended to it):

```js
import uniqueId from "lodash.uniqueid";

export default {
  props: {
    label: { required: true, type: String },
    done: { default: false, type: Boolean },
  },
  data() {
    return {
      isDone: this.done,
      id: uniqueId("todo-"),
    };
  },
};
```

Next, bind the `id` to both our checkbox's `id` attribute and the label's `for` attribute, updating the existing `id` and `for` attributes as shown:

```markup
<template>
  <div>
    <input type="checkbox" :id="id" :checked="isDone" />
    <label :for="id">{{ label }}</label>
  </div>
</template>
```

Summary
-------

And that will do for this article. At this point we have a nicely-working `ToDoItem` component that can be passed a label to display, will store its checked state, and will be rendered with a unique `id` each time it is called. You can check if the unique `id`s are working by temporarily adding more `<to-do-item></to-do-item>` calls into `App.vue`, and then checking their rendered output with your browser's DevTools.

Now we're ready to add multiple `ToDoItem` components to our app. In our next article we'll look at adding a set of todo item data to our `App.vue` component, which we'll then loop through and display inside `ToDoItem` components using the `v-for` directive.

* Previous
* Overview: Client-side JavaScript frameworks
* Next


Componentizing our React app - Learn web development

Componentizing our React app
============================

* Previous
* Overview: Client-side JavaScript frameworks
* Next

At this point, our app is a monolith. Before we can make it do things, we need to break it apart into manageable, descriptive components. React doesn't have any hard rules for what is and isn't a component – that's up to you! In this article we will show you a sensible way to break our app up into components.

|  |  |
| --- | --- |
| Prerequisites: |
 Familiarity with the core HTML,
 CSS, and
 JavaScript languages,
 knowledge of the
 terminal/command line.
  |
| Objective: | To show a sensible way of breaking our todo list app into components. |

Defining our first component
----------------------------

Defining a component can seem tricky until you have some practice, but the gist is:

* If it represents an obvious "chunk" of your app, it's probably a component
* If it gets reused often, it's probably a component.

That second bullet is especially valuable: making a component out of common UI elements allows you to change your code in one place and see those changes everywhere that component is used. You don't have to break everything out into components right away, either. Let's take the second bullet point as inspiration and make a component out of the most reused, most important piece of the UI: a todo list item.

Make a `<Todo />`
-----------------

Before we can make a component, we should create a new file for it. In fact, we should make a directory just for our components. Make sure you're in the root of your app before you run these commands!

```bash
# create a `components` directory
mkdir src/components
# within `components`, create a file called `Todo.jsx`
touch src/components/Todo.jsx
```

Don't forget to restart your development server if you stopped it to run the previous commands!

Let's add a `Todo()` function in `Todo.jsx`. Here, we define a function and export it:

```jsx
function Todo() {}

export default Todo;
```

This is OK so far, but our component should return something useful! Go back to `src/App.jsx`, copy the first `<li>` from inside the unordered list, and paste it into `Todo.jsx` so that it reads like this:

```jsx
function Todo() {
  return (
    <li className="todo stack-small">
 <div className="c-cb">
 <input id="todo-0" type="checkbox" defaultChecked />
 <label className="todo-label" htmlFor="todo-0">
 Eat
 </label>
 </div>
 <div className="btn-group">
 <button type="button" className="btn">
 Edit <span className="visually-hidden">Eat</span>
 </button>
 <button type="button" className="btn btn\_\_danger">
 Delete <span className="visually-hidden">Eat</span>
 </button>
 </div>
 </li>
  );
}

export default Todo;
```

Now we have something we can use. In `App.jsx`, add the following line at the top of the file to import `Todo`:

```jsx
import Todo from "./components/Todo";
```

With this component imported, you can replace all of the `<li>` elements in `App.jsx` with `<Todo />` component calls. Your `<ul>` should read like this:

```jsx
<ul
 role="list"
 className="todo-list stack-large stack-exception"
 aria-labelledby="list-heading">
 <Todo />
 <Todo />
 <Todo />
</ul>
```

When you return to your app, you'll notice something unfortunate: your list now repeats the first task three times!

![Our todo list app, with todo components repeating because the label is hardcoded into the component](/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_components/todo-list-repeating-todos.png)

We don't only want to eat; we have other things to — well — to do. Next we'll look at how we can make different component calls render unique content.

Make a unique `<Todo />`
------------------------

Components are powerful because they let us re-use pieces of our UI, and refer to one place for the source of that UI. The problem is, we don't typically want to reuse all of each component; we want to reuse most parts, and change small pieces. This is where props come in.

### What's in a `name`?

In order to track the names of tasks we want to complete, we should ensure that each `<Todo />` component renders a unique name.

In `App.jsx`, give each `<Todo />` a name prop. Let's use the names of our tasks that we had before:

```jsx
<Todo name="Eat" />
<Todo name="Sleep" />
<Todo name="Repeat" />
```

When your browser refreshes, you will see… the exact same thing as before. We gave our `<Todo />` some props, but we aren't using them yet. Let's go back to `Todo.jsx` and remedy that.

First modify your `Todo()` function definition so that it takes `props` as a parameter. You can `console.log()` your props if you'd like to check that they are being received by the component correctly.

Once you're confident that your component is getting its props, you can replace every occurrence of `Eat` with your `name` prop by reading `props.name`. Remember: `props.name` is a JSX expression, so you'll need to wrap it in curly braces.

Putting all that together, your `Todo()` function should read like this:

```jsx
function Todo(props) {
  return (
    <li className="todo stack-small">
 <div className="c-cb">
 <input id="todo-0" type="checkbox" defaultChecked={true} />
 <label className="todo-label" htmlFor="todo-0">
 {props.name}
 </label>
 </div>
 <div className="btn-group">
 <button type="button" className="btn">
 Edit <span className="visually-hidden">{props.name}</span>
 </button>
 <button type="button" className="btn btn\_\_danger">
 Delete <span className="visually-hidden">{props.name}</span>
 </button>
 </div>
 </li>
  );
}

export default Todo;
```

*Now* your browser should show three unique tasks. Another problem remains though: they're all still checked by default.

![Our todo list, with different todo labels now they are passed into the components as props](/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_components/todo-list-unique-todos.png)

### Is it `completed`?

In our original static list, only `Eat` was checked. Once again, we want to reuse *most* of the UI that makes up a `<Todo />` component, but change one thing. That's a good job for another prop! Give your first `<Todo />` call a boolean prop of `completed`, and leave the other two as they are.

```jsx
<Todo name="Eat" completed />
<Todo name="Sleep" />
<Todo name="Repeat" />
```

As before, we must go back to `Todo.jsx` to actually use these props. Change the `defaultChecked` attribute on the `<input />` so that its value is equal to the `completed` prop. Once you're done, the Todo component's `<input />` element will read like this:

```jsx
<input id="todo-0" type="checkbox" defaultChecked={props.completed} />
```

And your browser should update to show only `Eat` being checked:

![Our todo list app, now with differing checked states - some checkboxes are checked, others not](/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_components/todo-list-differing-checked-states.png)

If you change each `<Todo />` component's `completed` prop, your browser will check or uncheck the equivalent rendered checkboxes accordingly.

### Gimme some `id`, please

We have still *another* problem: our `<Todo />` component gives every task an `id` attribute of `todo-0`. This is bad for a couple of reasons:

* `id` attributes must be unique (they are used as unique identifiers for document fragments, by CSS, JavaScript, etc.).
* When `id`s are not unique, the functionality of label elements can break.

The second problem is affecting our app right now. If you click on the word "Sleep" next to the second checkbox, you'll notice the "Eat" checkbox toggles instead of the "Sleep" checkbox. This is because every checkbox's `<label>` element has an `htmlFor` attribute of `todo-0`. The `<label>`s only acknowledge the first element with a given `id` attribute, which causes the problem you see when clicking on the other labels.

We had unique `id` attributes before we created the `<Todo />` component. Let's bring them back, following the format of `todo-i`, where `i` gets larger by one every time. Update the `Todo` component instances inside `App.jsx` to add in `id` props, as follows:

```jsx
<Todo name="Eat" id="todo-0" completed />
<Todo name="Sleep" id="todo-1" />
<Todo name="Repeat" id="todo-2" />
```

**Note:** The `completed` prop is last here because it is a boolean with no assignment. This is purely a stylistic convention. The order of props does not matter because props are JavaScript objects, and JavaScript objects are unordered.

Now go back to `Todo.jsx` and make use of the `id` prop. It needs to replace the `<input />` element's `id` attribute value, as well as its `<label>`'s `htmlFor` attribute value:

```jsx
<div className="c-cb">
 <input id={props.id} type="checkbox" defaultChecked={props.completed} />
 <label className="todo-label" htmlFor={props.id}>
 {props.name}
 </label>
</div>
```

With these fixes in place, clicking on the labels next to each checkbox will do what we expect – check and uncheck the checkboxes next to those labels.

So far, so good?
----------------

We're making good use of React so far, but we could do better! Our code is repetitive. The three lines that render our `<Todo />` component are almost identical, with only one difference: the value of each prop.

We can clean up our code with one of JavaScript's core abilities: iteration. To use iteration, we should first re-think our tasks.

Tasks as data
-------------

Each of our tasks currently contains three pieces of information: its name, whether it has been checked, and its unique ID. This data translates nicely to an object. Since we have more than one task, an array of objects would work well in representing this data.

In `src/main.jsx`, declare a new `const` beneath the final import, but above `ReactDOM.createRoot()`:

```jsx
const DATA = [
  { id: "todo-0", name: "Eat", completed: true },
  { id: "todo-1", name: "Sleep", completed: false },
  { id: "todo-2", name: "Repeat", completed: false },
];
```

**Note:** If your text editor has an ESLint plugin, you may see a warning on this `DATA` const. This warning comes from the ESLint configuration supplied by the Vite template we used, and it doesn't apply to this code. You can safely suppress the warning by adding `// eslint-disable-next-line` to the line above the `DATA` const.

Next, we'll pass `DATA` to `<App />` as a prop, called `tasks`. Update your `<App />` component call inside `src/main.jsx` to read like this:

```jsx
<App tasks={DATA} />
```

The `DATA` array is now available inside the App component as `props.tasks`. You can `console.log()` it to check, if you'd like.

**Note:** `ALL_CAPS` constant names have no special meaning in JavaScript; they're a convention that tells other developers "this data will never change after being defined here".

Rendering with iteration
------------------------

To render our array of objects, we have to turn each object into a `<Todo />` component. JavaScript gives us an array method for transforming items into something else: `Array.prototype.map()`.

Inside `App.jsx`, create a new `const` above the `App()` function's `return` statement called `taskList`. Let's start by transforming each task in the `props.tasks` array into its `name`. The `?.` operator lets us perform optional chaining to check if `props.tasks` is `undefined` or `null` before attempting to create a new array of task names:

```jsx
const taskList = props.tasks?.map((task) => task.name);
```

Let's try replacing all the children of the `<ul>` with `taskList`:

```jsx
<ul
 role="list"
 className="todo-list stack-large stack-exception"
 aria-labelledby="list-heading">
 {taskList}
</ul>
```

This gets us some of the way towards showing all the components again, but we've got more work to do: the browser currently renders each task's name as plain text. We're missing our HTML structure — the `<li>` and its checkboxes and buttons!

![Our todo list app with the todo item labels just shown bunched up on one line](/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_components/todo-list-unstructured-names.png)

To fix this, we need to return a `<Todo />` component from our `map()` function — remember that JSX is JavaScript, so we can use it alongside any other, more familiar JavaScript syntax. Let's try the following instead of what we have already:

```jsx
const taskList = props.tasks?.map((task) => <Todo />);
```

Look again at your app; now our tasks look more like they used to, but they're missing the names of the tasks themselves. Remember that each task we map over contains the `id`, `name`, and `completed` properties we want to pass into our `<Todo />` component. If we put that knowledge together, we get code like this:

```jsx
const taskList = props.tasks?.map((task) => (
  <Todo id={task.id} name={task.name} completed={task.completed} />
));
```

Now the app looks like it did before, and our code is less repetitive.

Unique keys
-----------

Now that React is rendering our tasks out of an array, it has to keep track of which one is which in order to render them properly. React tries to do its own guesswork to keep track of things, but we can help it out by passing a `key` prop to our `<Todo />` components. `key` is a special prop that's managed by React – you cannot use the word `key` for any other purpose.

Because keys should be unique, we're going to re-use the `id` of each task object as its key. Update your `taskList` constant like so:

```jsx
const taskList = props.tasks?.map((task) => (
  <Todo
 id={task.id}
 name={task.name}
 completed={task.completed}
 key={task.id}
 />
));
```

**You should always pass a unique key to anything you render with iteration.** Nothing obvious will change in your browser, but if you do not use unique keys, React will log warnings to your console and your app may behave strangely!

Componentizing the rest of the app
----------------------------------

Now that we've got our most important component sorted out, we can turn the rest of our app into components. Remembering that components are either obvious pieces of UI, reused pieces of UI, or both, we can make two more components:

* `<Form />`
* `<FilterButton />`

Since we know we need both, we can batch some of the file creation work together in one terminal command. Run this command in your terminal, taking care that you're in the root directory of your app:

```bash
touch src/components/{Form,FilterButton}.jsx
```

### The `<Form />`

Open `components/Form.jsx` and do the following:

* Declare a `Form()` function and export it at the end of the file.
* Copy the `<form>` tags and everything between them from inside `App.jsx`, and paste them inside `Form()`'s `return` statement.

Your `Form.jsx` file should read like this:

```jsx
function Form() {
  return (
    <form>
 <h2 className="label-wrapper">
 <label htmlFor="new-todo-input" className="label\_\_lg">
 What needs to be done?
 </label>
 </h2>
 <input
 type="text"
 id="new-todo-input"
 className="input input\_\_lg"
 name="text"
 autoComplete="off"
 />
 <button type="submit" className="btn btn\_\_primary btn\_\_lg">
 Add
 </button>
 </form>
  );
}

export default Form;
```

### The `<FilterButton />`

Do the same things you did to create `Form.jsx` inside `FilterButton.jsx`, but call the component `FilterButton()` and copy the HTML for the first button inside `<div className="filters btn-group stack-exception">` from `App.jsx` into the `return` statement.

The file should read like this:

```jsx
function FilterButton() {
  return (
    <button type="button" className="btn toggle-btn" aria-pressed="true">
 <span className="visually-hidden">Show </span>
 <span>all </span>
 <span className="visually-hidden"> tasks</span>
 </button>
  );
}

export default FilterButton;
```

**Note:** You might notice that we are making the same mistake here as we first made for the `<Todo />` component, in that each button will be the same. That's fine! We're going to fix up this component later on, in Back to the filter buttons.

Importing all our components
----------------------------

Let's make use of our new components. Add some more `import` statements to the top of `App.jsx` and reference the components we've just made. Then, update the `return` statement of `App()` so that it renders our components.

When you're done, `App.jsx` will read like this:

```jsx
import Form from "./components/Form";
import FilterButton from "./components/FilterButton";
import Todo from "./components/Todo";

function App(props) {
  const taskList = props.tasks?.map((task) => (
    <Todo
 id={task.id}
 name={task.name}
 completed={task.completed}
 key={task.id}
 />
  ));
  return (
    <div className="todoapp stack-large">
 <h1>TodoMatic</h1>
 <Form />
 <div className="filters btn-group stack-exception">
 <FilterButton />
 <FilterButton />
 <FilterButton />
 </div>
 <h2 id="list-heading">3 tasks remaining</h2>
 <ul
 role="list"
 className="todo-list stack-large stack-exception"
 aria-labelledby="list-heading">
 {taskList}
 </ul>
 </div>
  );
}

export default App;
```

With this in place, your React app should render basically the same as it did before, but using your shiny new components.

Summary
-------

And that's it for this article — we've gone into depth on how to break up your app nicely into components and render them efficiently. Next we'll look at handling events in React, and start adding some interactivity.

* Previous
* Overview: Client-side JavaScript frameworks
* Next


Vue resources - Learn web development

Vue resources
=============

* Previous
* Overview: Client-side JavaScript frameworks
* Next

Now we'll round off our study of Vue by giving you a list of resources that you can use to go further in your learning, plus some other useful tips.

|  |  |
| --- | --- |
| Prerequisites: |
 Familiarity with the core HTML,
 CSS, and
 JavaScript languages,
 knowledge of the
 terminal/command line.

 Vue components are written as a combination of JavaScript objects that
 manage the app's data and an HTML-based template syntax that maps to
 the underlying DOM structure. For installation, and to use some of the
 more advanced features of Vue (like Single File Components or render
 functions), you'll need a terminal with node + npm installed.
  |
| Objective: |
 To learn where to go to find further information on Vue, to continue
 your learning.
  |

Further resources
-----------------

Here's where you should go to learn more about Vue:

* Vue Docs — The main Vue site. Contains comprehensive documentation, including examples, cookbooks, and reference material. This is the best place to start learning Vue in depth.
* Vue GitHub Repo — The Vue code itself. This is where you can report issues and/or contribute directly to the Vue codebase. Studying the Vue source code can help you better understand how the framework works, and write better code.
* Vue Forum — The official forum for getting help with Vue.
* Vue CLI Docs — Documentation for the Vue CLI. This contains information on customizing and extending the output you are generating via the CLI.
* NuxtJS — NuxtJS is a Server-Side Vue Framework, with some architectural opinions that can be useful to creating maintainable applications, even if you don't use any of the Server Side Rendering features it provides. This site provides detailed documentation on using NuxtJS.
* Vue Mastery — A paid education platform that specializes in Vue, including some free lessons.
* Vue School — Another paid education platform specializing in Vue.
Building and publishing your Vue app
------------------------------------

The Vue CLI also provides us with tools for preparing our app for publishing to the web. You can do this like so:

* If your local server is still running, end it by pressing `Ctrl` + `C` in the terminal.
* Next, run the `npm run build` (or `yarn build`) in the console.

This will create a new `dist` directory containing all of your production ready files. To publish your site to the web, copy the contents of this folder to your hosting environment.

**Note:** The Vue CLI docs also include a specific guide on how to publish your app to many of the common hosting platforms.

Vue 2
-----

 Vue 2 support will end on December 31st, 2023 and the default Vue version for all CLI tools will be version 3 and above.
 The Composition API works as an alternative to the property-based API where a `setup()` function is used on the component. Only what you return from this function is available in your `<template>`s. You are required to be explicit about "reactive" properties when using this API. Vue handles this for you using the Options API. This makes the new API typically considered a more advanced use case.

If you're upgrading from Vue 2, it's recommended you take a look at the Vue 3 migration guide.

* Previous
* Overview: Client-side JavaScript frameworks
* Next


Framework main features - Learn web development

Framework main features
=======================

* Previous
* Overview: Client-side JavaScript frameworks
* Next

Each major JavaScript framework has a different approach to updating the DOM, handling browser events, and providing an enjoyable developer experience. This article will explore the main features of "the big 4" frameworks, looking at how frameworks tend to work from a high level, and the differences between them.

|  |  |
| --- | --- |
| Prerequisites: |
 Familiarity with the core HTML,
 CSS, and
 JavaScript languages.
  |
| Objective: | To understand the main code features of frameworks. |

Domain-specific languages
-------------------------

All of the frameworks discussed in this module are powered by JavaScript, and all allow you to use domain-specific languages (DSLs) in order to build your applications. In particular, React has popularized the use of **JSX** for writing its components, while Ember utilizes **Handlebars**. Unlike HTML, these languages know how to read data variables, and this data can be used to streamline the process of writing your UI.

Angular apps often make heavy use of **TypeScript**. TypeScript is not concerned with the writing of user interfaces, but it is a domain-specific language, and has significant differences to vanilla JavaScript.

DSLs can't be read by the browser directly; they must be transformed into JavaScript or HTML first. Transformation is an extra step in the development process, but framework tooling generally includes the required tools to handle this step, or can be adjusted to include this step. While it is possible to build framework apps without using these domain-specific languages, embracing them will streamline your development process and make it easier to find help from the communities around those frameworks.

### JSX

JSX, which stands for JavaScript and XML, is an extension of JavaScript that brings HTML-like syntax to a JavaScript environment. It was invented by the React team for use in React applications, but can be used to develop other applications — like Vue apps, for instance.

The following shows a simple JSX example:

```jsx
const subject = "World";
const header = (
  <header>
 <h1>Hello, {subject}!</h1>
 </header>
);
```

This expression represents an HTML `<header>` element with an `<h1>` element inside. The curly braces around `{subject}` tell the application to read the value of the `subject` constant and insert it into our `<h1>`.

When used with React, the JSX from the previous snippet would be compiled into this:

```js
const subject = "World";
const header = React.createElement(
  "header",
  null,
  React.createElement("h1", null, "Hello, ", subject, "!"),
);
```

When ultimately rendered by the browser, the above snippet will produce HTML that looks like this:

```html
<header>
  <h1>Hello, World!</h1>
</header>
```

### Handlebars

The Handlebars templating language is not specific to Ember applications, but it is heavily utilized in Ember apps. Handlebars code resembles HTML, but it has the option of pulling data in from elsewhere. This data can be used to influence the HTML that an application ultimately builds.

Like JSX, Handlebars uses curly braces to inject the value of a variable. Handlebars uses a double-pair of curly braces, instead of a single pair.

Given this Handlebars template:

```html
<header>
  <h1>Hello, {{subject}}!</h1>
</header>
```

And this data:

```js
{
  subject: "World";
}
```

Handlebars will build HTML like this:

```html
<header>
  <h1>Hello, World!</h1>
</header>
```

### TypeScript

TypeScript is a *superset* of JavaScript, meaning it extends JavaScript — all JavaScript code is valid TypeScript, but not the other way around. TypeScript is useful for the strictness it allows developers to enforce on their code. For instance, consider a function `add()`, which takes integers `a` and `b` and returns their sum.

In JavaScript, that function could be written like this:

```js
function add(a, b) {
  return a + b;
}
```

This code might be trivial for someone accustomed to JavaScript, but it could still be clearer. JavaScript lets us use the `+` operator to concatenate strings together, so this function would technically still work if `a` and `b` were strings — it just might not give you the result you'd expect. What if we wanted to only allow numbers to be passed into this function? TypeScript makes that possible:

```ts
function add(a: number, b: number) {
  return a + b;
}
```

The `: number` written after each parameter here tells TypeScript that both `a` and `b` must be numbers. If we were to use this function and pass `'2'` into it as an argument, TypeScript would raise an error during compilation, and we would be forced to fix our mistake. We could write our own JavaScript that raises these errors for us, but it would make our source code significantly more verbose. It probably makes more sense to let TypeScript handle such checks for us.

Writing components
------------------

As mentioned in the previous chapter, most frameworks have some kind of component model. React components can be written with JSX, Ember components with Handlebars, and Angular and Vue components with a templating syntax that lightly extends HTML.

Regardless of their opinions on how components should be written, each framework's components offer a way to describe the external properties they may need, the internal state that the component should manage, and the events a user can trigger on the component's markup.

The code snippets in the rest of this section will use React as an example, and are written with JSX.

### Properties

Properties, or **props**, are external data that a component needs in order to render. Suppose you're building a website for an online magazine, and you need to be sure that each contributing writer gets credit for their work. You might create an `AuthorCredit` component to go with each article. This component needs to display a portrait of the author and a short byline about them. In order to know what image to render, and what byline to print, `AuthorCredit` needs to accept some props.

A React representation of this `AuthorCredit` component might look something like this:

```jsx
function AuthorCredit(props) {
  return (
    <figure>
 <img src={props.src} alt={props.alt} />
 <figcaption>{props.byline}</figcaption>
 </figure>
  );
}
```

`{props.src}`, `{props.alt}`, and `{props.byline}` represent where our props will be inserted into the component. To render this component, we would write code like this in the place where we want it rendered (which will probably be inside another component):

```jsx
<AuthorCredit
 src="./assets/zelda.png"
 alt="Portrait of Zelda Schiff"
 byline="Zelda Schiff is editor-in-chief of the Library Times."
/>
```

This will ultimately render the following `<figure>` element in the browser, with its structure as defined in the `AuthorCredit` component, and its content as defined in the props included on the `AuthorCredit` component call:

```html
<figure>
  <img src="assets/zelda.png" alt="Portrait of Zelda Schiff" />
  <figcaption>Zelda Schiff is editor-in-chief of the Library Times.</figcaption>
</figure>
```

### State

We talked about the concept of **state** in the previous chapter — a robust state-handling mechanism is key to an effective framework, and each component may have data that needs its state controlled. This state will persist in some way as long as the component is in use. Like props, state can be used to affect how a component is rendered.

As an example, consider a button that counts how many times it has been clicked. This component should be responsible for tracking its own *count* state, and could be written like this:

```jsx
function CounterButton() {
  const [count] = useState(0);
  return <button>Clicked {count} times</button>;
}
```

`useState()` is a **React hook** which, given an initial data value, will keep track of that value as it is updated. The code will be initially rendered like so in the browser:

```html
<button>Clicked 0 times</button>
```

The `useState()` call keeps track of the `count` value in a robust way across the app, without you needing to write code to do that yourself.

### Events

In order to be interactive, components need ways to respond to browser events, so our applications can respond to our users. Frameworks each provide their own syntax for listening to browser events, which reference the names of the equivalent native browser events.

In React, listening for the `click` event requires a special property, `onClick`. Let's update our `CounterButton` code from above to allow it to count clicks:

```jsx
function CounterButton() {
  const [count, setCount] = useState(0);
  return (
    <button onClick={() => setCount(count + 1)}>Clicked {count} times</button>
  );
}
```

In this version we are using additional `useState()` functionality to create a special `setCount()` function, which we can invoke to update the value of `count`. We call this function inside the `onClick` event handler to set `count` to whatever its current value is, plus one.

Styling components
------------------

Each framework offers a way to define styles for your components — or for the application as a whole. Although each framework's approach to defining the styles of a component is slightly different, all of them give you multiple ways to do so. With the addition of some helper modules, you can style your framework apps in Sass or Less, or transpile your CSS stylesheets with PostCSS.

Handling dependencies
---------------------

All major frameworks provide mechanisms for handling dependencies — using components inside other components, sometimes with multiple hierarchy levels. As with other features, the exact mechanism will differ between frameworks, but the end result is the same. Components tend to import components into other components using the standard JavaScript module syntax, or at least something similar.

### Components in components

One key benefit of component-based UI architecture is that components can be composed together. Just like you can write HTML tags inside each other to build a website, you can use components inside other components to build a web application. Each framework allows you to write components that utilize (and thus depend on) other components.

For example, our `AuthorCredit` React component might be utilized inside an `Article` component. That means that `Article` would need to import `AuthorCredit`.

```js
import AuthorCredit from "./components/AuthorCredit";
```

Once that's done, `AuthorCredit` could be used inside the `Article` component like this:

```jsx
<Article>
 <AuthorCredit />
</Article>
```

### Dependency injection

Real-world applications can often involve component structures with multiple levels of nesting. An `AuthorCredit` component nested many levels deep might, for some reason, need data from the very root level of our application.

Let's say that the magazine site we're building is structured like this:

```jsx
<App>
 <Home>
 <Article>
 <AuthorCredit {/\* props \*/} />
 </Article>
 </Home>
</App>
```

Our `App` component has data that our `AuthorCredit` component needs. We could rewrite `Home` and `Article` so that they know to pass props down, but this could get tedious if there are many, many levels between the origin and destination of our data. It's also excessive: `Home` and `Article` don't actually make use of the author's portrait or byline, but if we want to get that information into the `AuthorCredit`, we will need to change `Home` and `Article` to accommodate it.

The problem of passing data through many layers of components is called prop drilling, and it's not ideal for large applications.

To circumvent prop drilling, frameworks provide functionality known as dependency injection, which is a way to get certain data directly to the components that need it, without passing it through intervening levels. Each framework implements dependency injection under a different name, and in a different way, but the effect is ultimately the same.

Angular calls this process dependency injection; Vue has `provide()` and `inject()` component methods; React has a Context API; Ember shares state through services.

### Lifecycle

In the context of a framework, a component's **lifecycle** is a collection of phases a component goes through from the time it is appended to the DOM and then rendered by the browser (often called *mounting*) to the time that it is removed from the DOM (often called *unmounting*). Each framework names these lifecycle phases differently, and not all give developers access to the same phases. All of the frameworks follow the same general model: they allow developers to perform certain actions when the component *mounts*, when it *renders*, when it *unmounts*, and at many phases in between these.

The *render* phase is the most crucial to understand, because it is repeated the most times as your user interacts with your application. It's run every time the browser needs to render something new, whether that new information is an addition to what's in the browser, a deletion, or an edit of what's there.

This diagram of a React component's lifecycle offers a general overview of the concept.

Rendering elements
------------------

Just as with lifecycles, frameworks take different-but-similar approaches to how they render your applications. All of them track the current rendered version of your browser's DOM, and each makes slightly different decisions about how the DOM should change as components in your application re-render. Because frameworks make these decisions for you, you typically don't interact with the DOM yourself. This abstraction away from the DOM is more complex and more memory-intensive than updating the DOM yourself, but without it, frameworks could not allow you to program in the declarative way they're known for.

The **Virtual DOM** is an approach whereby information about your browser's DOM is stored in JavaScript memory. Your application updates this copy of the DOM, then compares it to the "real" DOM — the DOM that is actually rendered for your users — in order to decide what to render. The application builds a "diff" to compare the differences between the updated virtual DOM and the currently rendered DOM, and uses that diff to apply updates to the real DOM. Both React and Vue utilize a virtual DOM model, but they do not apply the exact same logic when diffing or rendering.

You can read more about the Virtual DOM in the React docs.

The **Incremental DOM** is similar to the virtual DOM in that it builds a DOM diff to decide what to render, but different in that it doesn't create a complete copy of the DOM in JavaScript memory. It ignores the parts of the DOM that do not need to be changed. Angular is the only framework discussed so far in this module that uses an incremental DOM.

You can read more about the Incremental DOM on the Auth0 blog.

The **Glimmer VM** is unique to Ember. It is not a virtual DOM nor an incremental DOM; it is a separate process through which Ember's templates are transpiled into a kind of "byte code" that is easier and faster to read than JavaScript.

Routing
-------

As mentioned in the previous chapter, routing is an important part of the web experience. To avoid a broken experience in sufficiently complex apps with lots of views, each of the frameworks covered in this module provides a library (or more than one library) that helps developers implement client-side routing in their applications.

Testing
-------

All applications benefit from test coverage that ensures your software continues to behave in the way that you'd expect, and web applications are no different. Each framework's ecosystem provides tooling that facilitates the writing of tests. Testing tools are not built into the frameworks themselves, but the command-line interface tools used to generate framework apps give you access to the appropriate testing tools.

Each framework has extensive tools in its ecosystem, with capabilities for unit and integration testing alike.

Testing Library is a suite of testing utilities that has tools for many JavaScript environments, including React, Vue, and Angular. The Ember docs cover the testing of Ember apps.

Here's a quick test for our `CounterButton` written with the help of React Testing Library — it tests a number of things, such as the button's existence, and whether the button is displaying the correct text after being clicked 0, 1, and 2 times:

```jsx
import { fireEvent, render, screen } from "@testing-library/react";

import CounterButton from "./CounterButton";

it("Renders a semantic button with an initial state of 0", () => {
  render(<CounterButton />);
  const btn = screen.getByRole("button");

  expect(btn).toBeInTheDocument();
  expect(btn).toHaveTextContent("Clicked 0 times");
});

it("Increments the count when clicked", () => {
  render(<CounterButton />);
  const btn = screen.getByRole("button");

  fireEvent.click(btn);
  expect(btn).toHaveTextContent("Clicked 1 times");

  fireEvent.click(btn);
  expect(btn).toHaveTextContent("Clicked 2 times");
});
```

Summary
-------

At this point you should have more of an idea about the actual languages, features, and tools you'll be using as you create applications with frameworks. I'm sure you're enthusiastic to get going and actually do some coding, and that's what you are going to do next! At this point you can choose which framework you'd like to start learning first:

* React
* Ember
* Vue
* Svelte
* Angular
* Previous
* Overview: Client-side JavaScript frameworks
* Next


Advanced Svelte: Reactivity, lifecycle, accessibility - Learn web development

Advanced Svelte: Reactivity, lifecycle, accessibility
=====================================================

* Previous
* Overview: Client-side JavaScript frameworks
* Next

In the last article we added more features to our to-do list and started to organize our app into components. In this article we will add the app's final features and further componentize our app. We will learn how to deal with reactivity issues related to updating objects and arrays. To avoid common pitfalls, we'll have to dig a little deeper into Svelte's reactivity system. We'll also look at solving some accessibility focus issues, and more besides.

|  |  |
| --- | --- |
| Prerequisites: |
 At minimum, it is recommended that you are familiar with the core
 HTML,
 CSS, and
 JavaScript languages, and
 have knowledge of the
 terminal/command line.

 You'll need a terminal with node and npm installed to compile and build
 your app.
  |
| Objective: |
 Learn some advanced Svelte techniques involving solving reactivity
 issues, keyboard accessibility problems to do with component lifecycle,
 and more.
  |

We'll focus on some accessibility issues involving focus management. To do so, we'll utilize some techniques for accessing DOM nodes and executing methods like `focus()` and `select()`. We will also see how to declare and clean up event listeners on DOM elements.

We also need to learn a bit about component lifecycle to understand when these DOM nodes get mounted and unmounted from the DOM and how we can access them. We will also learn about the `action` directive, which will allow us to extend the functionality of HTML elements in a reusable and declarative way.

Finally, we will learn a bit more about components. So far, we've seen how components can share data using props, and communicate with their parents using events and two-way data binding. Now we will see how components can also expose methods and variables.

The following new components will be developed throughout the course of this article:

* `MoreActions`: Displays the *Check All* and *Remove Completed* buttons, and emits the corresponding events required to handle their functionality.
* `NewTodo`: Displays the `<input>` field and *Add* button for adding a new to-do.
* `TodosStatus`: Displays the "x out of y items completed" status heading.
Code along with us
------------------

### Git

Clone the GitHub repo (if you haven't already done it) with:

```bash
git clone https://github.com/opensas/mdn-svelte-tutorial.git
```

Then to get to the current app state, run

```bash
cd mdn-svelte-tutorial/05-advanced-concepts
```

Or directly download the folder's content:

```bash
npx degit opensas/mdn-svelte-tutorial/05-advanced-concepts
```

Remember to run `npm install && npm run dev` to start your app in development mode.

### REPL

To code along with us using the REPL, start at

https://svelte.dev/repl/76cc90c43a37452e8c7f70521f88b698?version=3.23.2

Working on the MoreActions component
------------------------------------

Now we'll tackle the *Check All* and *Remove Completed* buttons. Let's create a component that will be in charge of displaying the buttons and emitting the corresponding events.

1. Create a new file, `components/MoreActions.svelte`.
2. When the first button is clicked, we'll emit a `checkAll` event to signal that all the to-dos should be checked/unchecked. When the second button is clicked, we'll emit a `removeCompleted` event to signal that all of the completed to-dos should be removed. Put the following content into your `MoreActions.svelte` file:

```svelte
<script>
 import { createEventDispatcher } from "svelte";
 const dispatch = createEventDispatcher();

 let completed = true;

 const checkAll = () => {
 dispatch("checkAll", completed);
 completed = !completed;
 };

 const removeCompleted = () => dispatch("removeCompleted");
</script>

<div class="btn-group">
  <button type="button" class="btn btn\_\_primary" on:click={checkAll}>{completed ? 'Check' : 'Uncheck'} all</button>
  <button type="button" class="btn btn\_\_primary" on:click={removeCompleted}>Remove completed</button>
</div>
```

We've also included a `completed` variable to toggle between checking and unchecking all tasks.
3. Back over in `Todos.svelte`, we are going to import our `MoreActions` component and create two functions to handle the events emitted by the `MoreActions` component.
 Add the following import statement below the existing ones:

```js
import MoreActions from "./MoreActions.svelte";
```

4. Then add the described functions at the end of the `<script>` section:

```js
const checkAllTodos = (completed) =>
  todos.forEach((t) => (t.completed = completed));

const removeCompletedTodos = () =>
  (todos = todos.filter((t) => !t.completed));
```

5. Now go to the bottom of the `Todos.svelte` markup section and replace the `<div class="btn-group">` element that we copied into `MoreActions.svelte` with a call to the `MoreActions` component, like so:

```svelte
<!-- MoreActions -->
<MoreActions
 on:checkAll={(e) => checkAllTodos(e.detail)}
 on:removeCompleted={removeCompletedTodos}
/>
```

6. OK, let's go back into the app and try it out. You'll find that the *Remove Completed* button works fine, but the *Check All*/*Uncheck All* button just silently fails.

To find out what is happening here, we'll have to dig a little deeper into Svelte reactivity.

Reactivity gotchas: updating objects and arrays
-----------------------------------------------

To see what's happening we can log the `todos` array from the `checkAllTodos()` function to the console.

1. Update your existing `checkAllTodos()` function to the following:

```js
const checkAllTodos = (completed) => {
  todos.forEach((t) => (t.completed = completed));
  console.log("todos", todos);
};
```

2. Go back to your browser, open your DevTools console, and click *Check All*/*Uncheck All* a few times.

You'll notice that the array is successfully updated every time you press the button (the `todo` objects' `completed` properties are toggled between `true` and `false`), but Svelte is not aware of that. This also means that in this case, a reactive statement like `$: console.log('todos', todos)` won't be very useful.

To find out why this is happening, we need to understand how reactivity works in Svelte when updating arrays and objects.

Many web frameworks use the virtual DOM technique to update the page. Basically, the virtual DOM is an in-memory copy of the contents of the web page. The framework updates this virtual representation, which is then synced with the "real" DOM. This is much faster than directly updating the DOM and allows the framework to apply many optimization techniques.

These frameworks, by default, basically re-run all our JavaScript on every change against this virtual DOM, and apply different methods to cache expensive calculations and optimize execution. They make little to no attempt to understand what our JavaScript code is doing.

Svelte doesn't use a virtual DOM representation. Instead, it parses and analyzes our code, creates a dependency tree, and then generates the required JavaScript to update only the parts of the DOM that need to be updated. This approach usually generates optimal JavaScript code with minimal overhead, but it also has its limitations.

Sometimes Svelte cannot detect changes to variables being watched. Remember that to tell Svelte that a variable has changed, you have to assign it a new value. A simple rule to keep in mind is that **The name of the updated variable must appear on the left-hand side of the assignment.**

For example, in the following piece of code:

```js
const foo = obj.foo;
foo.bar = "baz";
```

Svelte won't update references to `obj.foo.bar`, unless you follow it up with `obj = obj`. That's because Svelte can't track object references, so we have to explicitly tell it that `obj` has changed by issuing an assignment.

**Note:** If `foo` is a top-level variable, you can easily tell Svelte to update `obj` whenever `foo` is changed with the following reactive statement: `$: foo, obj = obj`. With this we are defining `foo` as a dependency, and whenever it changes Svelte will run `obj = obj`.

In our `checkAllTodos()` function, when we run:

```js
todos.forEach((t) => (t.completed = completed));
```

Svelte will not mark `todos` as changed because it does not know that when we update our `t` variable inside the `forEach()` method, we are also modifying the `todos` array. And that makes sense, because otherwise Svelte would be aware of the inner workings of the `forEach()` method; the same would therefore be true for any method attached to any object or array.

Nevertheless, there are different techniques that we can apply to solve this problem, and all of them involve assigning a new value to the variable being watched.

As we already saw, we could just tell Svelte to update the variable with a self-assignment, like this:

```js
const checkAllTodos = (completed) => {
  todos.forEach((t) => (t.completed = completed));
  todos = todos;
};
```

This will solve the problem. Internally Svelte will flag `todos` as changed and remove the apparently redundant self-assignment. Apart from the fact that it looks weird, it's perfectly OK to use this technique, and sometimes it's the most concise way to do it.

We could also access the `todos` array by index, like this:

```js
const checkAllTodos = (completed) => {
  todos.forEach((t, i) => (todos[i].completed = completed));
};
```

Assignments to properties of arrays and objects — e.g. `obj.foo += 1` or `array[i] = x` — work the same way as assignments to the values themselves. When Svelte analyzes this code, it can detect that the `todos` array is being modified.

Another solution is to assign a new array to `todos` containing a copy of all the to-dos with the `completed` property updated accordingly, like this:

```js
const checkAllTodos = (completed) => {
  todos = todos.map((t) => ({ ...t, completed }));
};
```

In this case we are using the `map()` method, which returns a new array with the results of executing the provided function for each item. The function returns a copy of each to-do using spread syntax and overwrites the property of the completed value accordingly. This solution has the added benefit of returning a new array with new objects, completely avoiding mutating the original `todos` array.

**Note:** Svelte allows us to specify different options that affect how the compiler works. The `<svelte:options immutable={true}/>` option tells the compiler that you promise not to mutate any objects. This allows it to be less conservative about checking whether values have changed and generate simpler and more performant code. For more information on `<svelte:options>`, check the Svelte options documentation.

All of these solutions involve an assignment in which the updated variable is on the left side of the equation. Any of this techniques will allow Svelte to notice that our `todos` array has been modified.

**Choose one, and update your `checkAllTodos()` function as required. Now you should be able to check and uncheck all your to-dos at once. Try it!**

Finishing our MoreActions component
-----------------------------------

We will add one usability detail to our component. We'll disable the buttons when there are no tasks to be processed. To create this, we'll receive the `todos` array as a prop, and set the `disabled` property of each button accordingly.

1. Update your `MoreActions.svelte` component like this:

```svelte
<script>
 import { createEventDispatcher } from 'svelte';
 const dispatch = createEventDispatcher();

 export let todos;

 let completed = true;

 const checkAll = () => {
 dispatch('checkAll', completed);
 completed = !completed;
 }

 const removeCompleted = () => dispatch('removeCompleted');

 $: completedTodos = todos.filter((t) => t.completed).length;
</script>

<div class="btn-group">
  <button type="button" class="btn btn\_\_primary"
 disabled={todos.length === 0} on:click={checkAll}>{completed ? 'Check' : 'Uncheck'} all</button>
  <button type="button" class="btn btn\_\_primary"
 disabled={completedTodos === 0} on:click={removeCompleted}>Remove completed</button>
</div>
```

We've also declared a reactive `completedTodos` variable to enable or disable the *Remove Completed* button.
2. Don't forget to pass the prop into `MoreActions` from inside `Todos.svelte`, where the component is called:

```svelte
<MoreActions {todos}
 on:checkAll={(e) => checkAllTodos(e.detail)}
 on:removeCompleted={removeCompletedTodos}
 />
```

Working with the DOM: focusing on the details
---------------------------------------------

Now that we have completed all of the app's required functionality, we'll concentrate on some accessibility features that will improve the usability of our app for both keyboard-only and screen reader users.

In its current state our app has a couple of keyboard accessibility problems involving focus management. Let's have a look at these issues.

Exploring keyboard accessibility issues in our to-do app
--------------------------------------------------------

Right now, keyboard users will find out that the focus flow of our app is not very predictable or coherent.

If you click on the input at the top of our app, you'll see a thick, dashed outline around that input. This outline is your visual indicator that the browser is currently focused on this element.

If you are a mouse user, you might have skipped this visual hint. But if you are working exclusively with the keyboard, knowing which control has focus is of vital importance. It tells us which control is going to receive our keystrokes.

If you press the `Tab` key repeatedly, you'll see the dashed focus indicator cycling between all the focusable elements on the page. If you move the focus to the *Edit* button and press `Enter`, suddenly the focus disappears, and you can no longer tell which control will receive our keystrokes.

Moreover, if you press the `Escape` or `Enter` key, nothing happens. And if you click on *Cancel* or *Save*, the focus disappears again. For a user working with the keyboard, this behavior will be confusing at best.

We'd also like to add some usability features, like disabling the *Save* button when required fields are empty, giving focus to certain HTML elements or auto-selecting contents when a text input receives focus.

To implement all these features, we'll need programmatic access to DOM nodes to run functions like `focus()` and `select()`. We will also have to use `addEventListener()` and `removeEventListener()` to run specific tasks when the control receives focus.

The problem is that all these DOM nodes are dynamically created by Svelte at runtime. So we'll have to wait for them to be created and added to the DOM in order to use them. To do so, we'll have to learn about the component lifecycle to understand when we can access them — more on this later.

Creating a NewTodo component
----------------------------

Let's begin by extracting our new to-do form out to its own component. With what we know so far we can create a new component file and adjust the code to emit an `addTodo` event, passing the name of the new to-do in with the additional details.

1. Create a new file, `components/NewTodo.svelte`.
2. Put the following contents inside it:

```svelte
<script>
 import { createEventDispatcher } from 'svelte';
 const dispatch = createEventDispatcher();

 let name = '';

 const addTodo = () => {
 dispatch('addTodo', name);
 name = '';
 }

 const onCancel = () => name = '';

</script>

<form on:submit|preventDefault={addTodo} on:keydown={(e) => e.key === 'Escape' && onCancel()}>
  <h2 class="label-wrapper">
    <label for="todo-0" class="label\_\_lg">What needs to be done?</label>
  </h2>
  <input bind:value={name} type="text" id="todo-0" autoComplete="off" class="input input\_\_lg" />
  <button type="submit" disabled={!name} class="btn btn\_\_primary btn\_\_lg">Add</button>
</form>
```

Here we are binding the `<input>` to the `name` variable with `bind:value={name}` and disabling the *Add* button when it is empty (i.e. no text content) using `disabled={!name}`. We are also taking care of the `Escape` key with `on:keydown={(e) => e.key === 'Escape' && onCancel()}`. Whenever the `Escape` key is pressed we run `onCancel()`, which just clears up the `name` variable.
3. Now we have to `import` and use it from inside the `Todos` component, and update the `addTodo()` function to receive the name of the new todo.
 Add the following `import` statement below the others inside `Todos.svelte`:

```js
import NewTodo from "./NewTodo.svelte";
```

4. And update the `addTodo()` function like so:

```js
function addTodo(name) {
  todos = [...todos, { id: newTodoId, name, completed: false }];
}
```

`addTodo()` now receives the name of the new to-do directly, so we no longer need the `newTodoName` variable to give it its value. Our `NewTodo` component takes care of that.

**Note:** The `{ name }` syntax is just a shorthand for `{ name: name }`. This one comes from JavaScript itself and has nothing to do with Svelte, besides providing some inspiration for Svelte's own shorthands.
5. Finally for this section, replace the NewTodo form markup with a call to `NewTodo` component, like so:

```svelte
<!-- NewTodo -->
<NewTodo on:addTodo={(e) => addTodo(e.detail)} />
```

Working with DOM nodes using the `bind:this={dom_node}` directive
-----------------------------------------------------------------

Now we want the `<input>`element of the `NewTodo` component to re-gain focus every time the *Add* button is pressed. For that we'll need a reference to the DOM node of the input. Svelte provides a way to do this with the `bind:this={dom_node}` directive. When specified, as soon as the component is mounted and the DOM node is created, Svelte assigns a reference to the DOM node to the specified variable.

We'll create a `nameEl` variable and bind it to the input using `bind:this={nameEl}`. Then inside `addTodo()`, after adding the new to-do we will call `nameEl.focus()` to refocus the `<input>` again. We will do the same when the user presses the `Escape` key, with the `onCancel()` function.

Update the contents of `NewTodo.svelte` like so:

```svelte
<script>
 import { createEventDispatcher } from 'svelte';
 const dispatch = createEventDispatcher();

 let name = '';
 let nameEl; // reference to the name input DOM node

 const addTodo = () => {
 dispatch('addTodo', name);
 name = '';
 nameEl.focus(); // give focus to the name input
 }

 const onCancel = () => {
 name = '';
 nameEl.focus(); // give focus to the name input
 }
</script>

<form on:submit|preventDefault={addTodo} on:keydown={(e) => e.key === 'Escape' && onCancel()}>
  <h2 class="label-wrapper">
    <label for="todo-0" class="label\_\_lg">What needs to be done?</label>
  </h2>
  <input bind:value={name} bind:this={nameEl} type="text" id="todo-0" autoComplete="off" class="input input\_\_lg" />
  <button type="submit" disabled={!name} class="btn btn\_\_primary btn\_\_lg">Add</button>
</form>
```

Try the app out: type a new to-do name in to the `<input>` field, press `tab` to give focus to the *Add* button, and then hit `Enter` or `Escape` to see how the input recovers focus.

### Autofocusing our input

The next feature will add to our `NewTodo` component will be an `autofocus` prop, which will allow us to specify that we want the `<input>` field to be focused on page load.

1. Our first attempt is as follows: let's try adding the `autofocus` prop and just call `nameEl.focus()` from the `<script>` block. Update the first part of the `<script>` section of `NewTodo.svelte` (the first four lines) to look like this:

```svelte
<script>
  import { createEventDispatcher } from 'svelte';
  const dispatch = createEventDispatcher();

  export let autofocus = false;

  let name = '';
  let nameEl; // reference to the name input DOM node

  if (autofocus) nameEl.focus();
```

2. Now go back to the `Todos` component and pass the `autofocus` prop into the `<NewTodo>` component call, like so:

```svelte
<!-- NewTodo -->
<NewTodo autofocus on:addTodo={(e) => addTodo(e.detail)} />
```

3. If you try your app out now, you'll see that the page is now blank, and in your DevTools web console you'll see an error along the lines of: `TypeError: nameEl is undefined`.

To understand what's happening here, let's talk some more about that component lifecycle we mentioned earlier.

Component lifecycle, and the `onMount()` function
-------------------------------------------------

When a component is instantiated, Svelte runs the initialization code (that is, the `<script>` section of the component). But at that moment, all the nodes that comprise the component are not attached to the DOM, in fact, they don't even exist.

So how can you know when the component has already been created and mounted on the DOM? The answer is that every component has a lifecycle that starts when it is created and ends when it is destroyed. There are a handful of functions that allow you to run code at key moments during that lifecycle.

The one you'll use most frequently is `onMount()`, which lets us run a callback as soon as the component has been mounted on the DOM. Let's give it a try and see what happens to the `nameEl` variable.

1. To start with, add the following line at the beginning of the `<script>` section of `NewTodo.svelte`:

```js
import { onMount } from "svelte";
```

2. And these lines at the end of it:

```js
console.log("initializing:", nameEl);
onMount(() => {
  console.log("mounted:", nameEl);
});
```

3. Now remove the `if (autofocus) nameEl.focus()` line to avoid throwing the error we were seeing before.
4. The app will now work again, and you'll see the following in your console:
```

initializing: undefined
mounted: <input id="todo-0" class="input input__lg" type="text" autocomplete="off">
```

As you can see, while the component is initializing, `nameEl` is undefined, which makes sense because the `<input>` node doesn't even exist yet. After the component has been mounted, Svelte assigned a reference to the `<input>` DOM node to the `nameEl` variable, thanks to the `bind:this={nameEl} directive`.
5. To get the autofocus functionality working, replace the previous `console.log()`/`onMount()` block you added with this:

```js
onMount(() => autofocus && nameEl.focus()); // if autofocus is true, we run nameEl.focus()
```

6. Go to your app again, and you'll now see the `<input>` field is focused on page load.

**Note:** You can have a look at the other lifecycle functions in the Svelte docs, and you can see them in action in the interactive tutorial.

Waiting for the DOM to be updated with the `tick()` function
------------------------------------------------------------

Now we will take care of the `Todo` component's focus management details. First of all, we want a `Todo` component's edit `<input>` to receive focus when we enter editing mode by pressing its *Edit* button. In the same fashion as we saw earlier, we'll create a `nameEl` variable inside `Todo.svelte` and call `nameEl.focus()` after setting the `editing` variable to `true`.

1. Open the file `components/Todo.svelte` and add a `nameEl` variable declaration just below your editing and name declarations:

```js
let nameEl; // reference to the name input DOM node
```

2. Now update your `onEdit()` function like so:

```js
function onEdit() {
  editing = true; // enter editing mode
  nameEl.focus(); // set focus to name input
}
```

3. And finally, bind `nameEl` to the `<input>` field by updating it like so:

```svelte
<input
 bind:value={name}
 bind:this={nameEl}
 type="text"
 id="todo-{todo.id}"
 autocomplete="off"
 class="todo-text" />
```

4. However, when you try the updated app, you'll get an error along the lines of "TypeError: nameEl is undefined" in the console when you press a to-do's *Edit* button.

So, what is happening here? When you update a component's state in Svelte, it doesn't update the DOM immediately. Instead, it waits until the next microtask to see if there are any other changes that need to be applied, including in other components. Doing so avoids unnecessary work and allows the browser to batch things more effectively.

In this case, when `editing` is `false`, the edit `<input>` is not visible because it does not exist in the DOM. Inside the `onEdit()` function we set `editing = true` and immediately afterwards try to access the `nameEl` variable and execute `nameEl.focus()`. The problem here is that Svelte hasn't yet updated the DOM.

One way to solve this problem is to use `setTimeout()` to delay the call to `nameEl.focus()` until the next event cycle, and give Svelte the opportunity to update the DOM.

Try this now:

```js
function onEdit() {
  editing = true; // enter editing mode
  setTimeout(() => nameEl.focus(), 0); // asynchronous call to set focus to name input
}
```

The above solution works, but it is rather inelegant. Svelte provides a better way to handle these cases. The `tick()` function returns a promise that resolves as soon as any pending state changes have been applied to the DOM (or immediately, if there are no pending state changes). Let's try it now.

1. First of all, import `tick` at the top of the `<script>` section alongside your existing import:

```js
import { tick } from "svelte";
```

2. Next, call `tick()` with `await` from an async function; update `onEdit()` like so:

```js
async function onEdit() {
  editing = true; // enter editing mode
  await tick();
  nameEl.focus();
}
```

3. If you try it now you'll see that everything works as expected.

**Note:** To see another example using `tick()`, visit the Svelte tutorial.

Adding functionality to HTML elements with the `use:action` directive
---------------------------------------------------------------------

Next up, we want the name `<input>` to automatically select all text on focus. Moreover, we want to develop this in such a way that it could be easily reused on any HTML `<input>` and applied in a declarative way. We will use this requirement as an excuse to show a very powerful feature that Svelte provides us to add functionality to regular HTML elements: actions.

To select the text of a DOM input node, we have to call `select()`. To get this function called whenever the node gets focused, we need an event listener along these lines:

```js
node.addEventListener("focus", (event) => node.select());
```

And, in order to avoid memory leaks, we should also call the `removeEventListener()` function when the node is destroyed.

**Note:** All this is just standard WebAPI functionality; nothing here is specific to Svelte.

We could achieve all this in our `Todo` component whenever we add or remove the `<input>` from the DOM, but we would have to be very careful to add the event listener after the node has been added to the DOM, and remove the listener before the node is removed from the DOM. In addition, our solution would not be very reusable.

That's where Svelte actions come into play. Basically they let us run a function whenever an element has been added to the DOM, and after removal from the DOM.

In our immediate use case, we will define a function called `selectOnFocus()` that will receive a node as a parameter. The function will add an event listener to that node so that whenever it gets focused it will select the text. Then it will return an object with a `destroy` property. The `destroy` property is what Svelte will execute after removing the node from the DOM. Here we will remove the listener to make sure we don't leave any memory leak behind.

1. Let's create the function `selectOnFocus()`. Add the following to the bottom of the `<script>` section of `Todo.svelte`:

```js
function selectOnFocus(node) {
  if (node && typeof node.select === "function") {
    // make sure node is defined and has a select() method
    const onFocus = (event) => node.select(); // event handler
    node.addEventListener("focus", onFocus); // when node gets focus call onFocus()
    return {
      destroy: () => node.removeEventListener("focus", onFocus), // this will be executed when the node is removed from the DOM
    };
  }
}
```

2. Now we need to tell the `<input>` to use that function with the `use:action` directive:

```svelte
<input use:selectOnFocus />
```

With this directive we are telling Svelte to run this function, passing the DOM node of the `<input>` as a parameter, as soon as the component is mounted on the DOM. It will also be in charge of executing the `destroy` function when the component is removed from DOM. So with the `use` directive, Svelte takes care of the component's lifecycle for us.
 In our case, our `<input>` would end up like so: update the component's first label/input pair (inside the edit template) as follows:

```svelte
<label for="todo-{todo.id}" class="todo-label">New name for '{todo.name}'</label>
<input
 bind:value={name}
 bind:this={nameEl}
 use:selectOnFocus
 type="text"
 id="todo-{todo.id}"
 autocomplete="off"
 class="todo-text" />
```

3. Let's try it out. Go to your app, press a to-do's *Edit* button, then `Tab` to take focus away from the `<input>`. Now click on the `<input>`, and you'll see that the entire input text is selected.
### Making the action reusable

Now let's make this function truly reusable across components. `selectOnFocus()` is just a function without any dependency on the `Todo.svelte` component, so we can just extract it to a file and use it from there.

1. Create a new file, `actions.js`, inside the `src` folder.
2. Give it the following content:

```js
export function selectOnFocus(node) {
  if (node && typeof node.select === "function") {
    // make sure node is defined and has a select() method
    const onFocus = (event) => node.select(); // event handler
    node.addEventListener("focus", onFocus); // when node gets focus call onFocus()
    return {
      destroy: () => node.removeEventListener("focus", onFocus), // this will be executed when the node is removed from the DOM
    };
  }
}
```

3. Now import it from inside `Todo.svelte`; add the following import statement just below the others:

```js
import { selectOnFocus } from "../actions.js";
```

4. And remove the `selectOnFocus()` definition from `Todo.svelte`, since we no longer need it there.
### Reusing our action

To demonstrate our action's reusability, let's make use of it in `NewTodo.svelte`.

1. Import `selectOnFocus()` from `actions.js` in this file too, as before:

```js
import { selectOnFocus } from "../actions.js";
```

2. Add the `use:selectOnFocus` directive to the `<input>`, like this:

```svelte
<input
 bind:value={name}
 bind:this={nameEl}
 use:selectOnFocus
 type="text"
 id="todo-0"
 autocomplete="off"
 class="input input\_\_lg" />
```

With a few lines of code we can add functionality to regular HTML elements in a very reusable and declarative way. It just takes an `import` and a short directive like `use:selectOnFocus` that clearly describes its purpose. And we can achieve this without the need to create a custom wrapper element like `TextInput`, `MyInput`, or similar. Moreover, you can add as many `use:action` directives as you want to an element.

Also, we didn't have to struggle with `onMount()`, `onDestroy()`, or `tick()` — the `use` directive takes care of the component lifecycle for us.

### Other actions improvements

In the previous section, while working with the `Todo` components, we had to deal with `bind:this`, `tick()`, and `async` functions just to give focus to our `<input>` as soon as it was added to the DOM.

1. This is how we can implement it with actions instead:

```js
const focusOnInit = (node) =>
  node && typeof node.focus === "function" && node.focus();
```

2. And then in our markup we just need to add another `use:` directive:

```svelte
<input bind:value={name} use:selectOnFocus use:focusOnInit />
```

3. Our `onEdit()` function can now be much simpler:

```js
function onEdit() {
  editing = true; // enter editing mode
}
```

As a last example before we move on, let's go back to our `Todo.svelte` component and give focus to the *Edit* button after the user presses *Save* or *Cancel*.

We could try just reusing our `focusOnInit` action again, adding `use:focusOnInit` to the *Edit* button. But we'd be introducing a subtle bug. When you add a new to-do, the focus will be put on the *Edit* button of the recently added to-do. That's because the `focusOnInit` action is running when the component is created.

That's not what we want — we want the *Edit* button to receive focus only when the user has pressed *Save* or *Cancel*.

1. So, go back to your `Todo.svelte` file.
2. First we'll create a flag named `editButtonPressed` and initialize it to `false`. Add this just below your other variable definitions:

```js
let editButtonPressed = false; // track if edit button has been pressed, to give focus to it after cancel or save
```

3. Next we'll modify the *Edit* button's functionality to save this flag, and create the action for it. Update the `onEdit()` function like so:

```js
function onEdit() {
  editButtonPressed = true; // user pressed the Edit button, focus will come back to the Edit button
  editing = true; // enter editing mode
}
```

4. Below it, add the following definition for `focusEditButton()`:

```js
const focusEditButton = (node) => editButtonPressed && node.focus();
```

5. Finally we `use` the `focusEditButton` action on the *Edit* button, like so:

```svelte
<button type="button" class="btn" on:click={onEdit} use:focusEditButton>
  Edit<span class="visually-hidden"> {todo.name}</span>
</button>
```

6. Go back and try your app again. At this point, every time the *Edit* button is added to the DOM, the `focusEditButton` action is executed, but it will only give focus to the button if the `editButtonPressed` flag is `true`.

**Note:** We have barely scratched the surface of actions here. Actions can also have reactive parameters, and Svelte lets us detect when any of those parameters change. So we can add functionality that integrates nicely with the Svelte reactive system. For a more detailed introduction to actions, consider checking out the Svelte Interactive tutorial or the Svelte `use:action` documentation.

Component binding: exposing component methods and variables using the `bind:this={component}` directive
-------------------------------------------------------------------------------------------------------

There's still one accessibility annoyance left. When the user presses the *Delete* button, the focus vanishes.

The last feature we will be looking at in this article involves setting the focus on the status heading after a to-do has been deleted.

Why the status heading? In this case, the element that had the focus has been deleted, so there's not a clear candidate to receive focus. We've picked the status heading because it's near the list of to-dos, and it's a way to give a visual feedback about the removal of the task, as well as indicating what's happened to screen reader users.

First we'll extract the status heading to its own component.

1. Create a new file, `components/TodosStatus.svelte`.
2. Add the following contents to it:

```svelte
<script>
 export let todos;

 $: totalTodos = todos.length;
 $: completedTodos = todos.filter((todo) => todo.completed).length;
</script>

<h2 id="list-heading">
  {completedTodos} out of {totalTodos} items completed
</h2>
```

3. Import the file at the beginning of `Todos.svelte`, adding the following `import` statement below the others:

```js
import TodosStatus from "./TodosStatus.svelte";
```

4. Replace the `<h2>` status heading inside `Todos.svelte` with a call to the `TodosStatus` component, passing `todos` to it as a prop, like so:

```svelte
<TodosStatus {todos} />
```

5. You can also do a bit of cleanup, removing the `totalTodos` and `completedTodos` variables from `Todos.svelte`. Just remove the `$: totalTodos = …` and the `$: completedTodos = …` lines, and also remove the reference to `totalTodos` when we calculate `newTodoId` and use `todos.length` instead. To do this, replace the block that begins with `let newTodoId` with this:

```js
$: newTodoId = todos.length ? Math.max(...todos.map((t) => t.id)) + 1 : 1;
```

6. Everything works as expected — we just extracted the last piece of markup to its own component.

Now we need to find a way to give focus to the `<h2>` status label after a to-do has been removed.

So far we saw how to send information to a component via props, and how a component can communicate with its parent by emitting events or using two-way data binding. The child component could get a reference to the `<h2>` node `using bind:this={dom_node}` and expose it to the outside using two-way data binding. But doing so would break the component encapsulation; setting focus on it should be its own responsibility.

So we need the `TodosStatus` component to expose a method that its parent can call to give focus to it. It's a very common scenario that a component needs to expose some behavior or information to the consumer; let's see how to achieve it with Svelte.

We've already seen that Svelte uses `export let varname = …` to declare props. But if instead of using `let` you export a `const`, `class`, or `function`, it is read-only outside the component. Function expressions are valid props, however. In the following example, the first three declarations are props, and the rest are exported values:

```svelte
<script>
 export let bar = "optional default initial value"; // prop
 export let baz = undefined; // prop
 export let format = (n) => n.toFixed(2); // prop

 // these are readonly
 export const thisIs = "readonly"; // read-only export

 export function greet(name) {
 // read-only export
 alert(`Hello, ${name}!`);
 }

 export const greet = (name) => alert(`Hello, ${name}!`); // read-only export
</script>
```

With this in mind, let's go back to our use case. We'll create a function called `focus()` that gives focus to the `<h2>` heading. For that we'll need a `headingEl` variable to hold the reference to the DOM node, and we'll have to bind it to the `<h2>` element using `bind:this={headingEl}`. Our focus method will just run `headingEl.focus()`.

1. Update the contents of `TodosStatus.svelte` like so:

```svelte
<script>
 export let todos;

 $: totalTodos = todos.length;
 $: completedTodos = todos.filter((todo) => todo.completed).length;

 let headingEl;

 export function focus() {
 // shorter version: export const focus = () => headingEl.focus()
 headingEl.focus();
 }
</script>

<h2 id="list-heading" bind:this={headingEl} tabindex="-1">
  {completedTodos} out of {totalTodos} items completed
</h2>
```

Note that we've added a `tabindex` attribute to the `<h2>` to allow the element to receive focus programmatically.
 As we saw earlier, using the `bind:this={headingEl}` directive gives us a reference to the DOM node in the variable `headingEl`. Then we use `export function focus()` to expose a function that gives focus to the `<h2>` heading.
 How can we access those exported values from the parent? Just as you can bind to DOM elements with the `bind:this={dom_node}` directive, you can also bind to component instances themselves with `bind:this={component}`. So, when you use `bind:this` on an HTML element, you get a reference to the DOM node, and when you do it on a Svelte component, you get a reference to the instance of that component.
2. So to bind to the instance of `TodosStatus`, we'll first create a `todosStatus` variable in `Todos.svelte`. Add the following line below your `import` statements:

```js
let todosStatus; // reference to TodosStatus instance
```

3. Next, add a `bind:this={todosStatus}` directive to the call, as follows:

```svelte
<!-- TodosStatus -->
<TodosStatus bind:this={todosStatus} {todos} />
```

4. Now we can call the `exported focus()` method from our `removeTodo()` function:

```js
function removeTodo(todo) {
  todos = todos.filter((t) => t.id !== todo.id);
  todosStatus.focus(); // give focus to status heading
}
```

5. Go back to your app. Now if you delete any to-do, the status heading will be focussed. This is useful to highlight the change in numbers of to-dos, both to sighted users and screen reader users.

**Note:** You might be wondering why we need to declare a new variable for component binding. Why can't we just call `TodosStatus.focus()`? You might have multiple `TodosStatus` instances active, so you need a way to reference each particular instance. That's why you have to specify a variable to bind each specific instance to.

The code so far
---------------

### Git

To see the state of the code as it should be at the end of this article, access your copy of our repo like this:

```bash
cd mdn-svelte-tutorial/06-stores
```

Or directly download the folder's content:

```bash
npx degit opensas/mdn-svelte-tutorial/06-stores
```

Remember to run `npm install && npm run dev` to start your app in development mode.

### REPL

To see the current state of the code in a REPL, visit:

https://svelte.dev/repl/d1fa84a5a4494366b179c87395940039?version=3.23.2

Summary
-------

In this article we have finished adding all the required functionality to our app, plus we've taken care of a number of accessibility and usability issues. We also finished splitting our app into manageable components, each one with a unique responsibility.

In the meantime, we saw a few advanced Svelte techniques, like:

* Dealing with reactivity gotchas when updating objects and arrays
* Working with DOM nodes using `bind:this={dom_node}` (binding DOM elements)
* Using the component lifecycle `onMount()` function
* Forcing Svelte to resolve pending state changes with the `tick()` function
* Adding functionality to HTML elements in a reusable and declarative way with the `use:action` directive
* Accessing component methods using `bind:this={component}` (binding components)

In the next article we will see how to use stores to communicate between components, and add animations to our components.

* Previous
* Overview: Client-side JavaScript frameworks
* Next