Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Restyled by prettier-markdown #1781

Merged
merged 6 commits into from
Mar 7, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 8 additions & 8 deletions src/pages/docs/javascript/for-loops.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,18 +19,18 @@ The **for statement** creates a loop that consists of three optional expressions
for ([initialization]; [condition]; [final-expression])
statement

`initialization`
`initialization`
An expression (including assignment expressions) or variable declaration evaluated once before the loop begins. Typically used to initialize a counter variable. This expression may optionally declare new variables with `var` or `let` keywords. Variables declared with `var` are not local to the loop, i.e. they are in the same scope the `for` loop is in. Variables declared with `let` are local to the statement.

The result of this expression is discarded.

`condition`
`condition`
An expression to be evaluated before each loop iteration. If this expression evaluates to true, `statement` is executed. This conditional test is optional. If omitted, the condition always evaluates to true. If the expression evaluates to false, execution skips to the first expression following the `for` construct.

`final-expression`
`final-expression`
An expression to be evaluated at the end of each loop iteration. This occurs before the next evaluation of `condition`. Generally used to update or increment the counter variable.

`statement`
`statement`
A statement that is executed as long as the condition evaluates to true. To execute multiple statements within the loop, use a [block](block) statement (`{ ... }`) to group those statements. To execute no statement within the loop, use an [empty](empty) statement (`;`).

## Examples
Expand Down Expand Up @@ -123,10 +123,10 @@ The `for...in` iterates over all [enumerable properties](https://developer.mozil
for (variable in object)
statement

`variable`
`variable`
A different property name is assigned to `variable` on each iteration.

`object`
`object`
Object whose non-Symbol enumerable properties are iterated over.

## Description
Expand Down Expand Up @@ -219,10 +219,10 @@ The `for await...of` creates a loop iterating over async iterable objects as wel
statement
}

`variable`
`variable`
On each iteration a value of a different property is assigned to `variable`. `variable` may be declared with `const`, `let`, or `var`.

`iterable`
`iterable`
Object whose iterable properties are to be iterated over.

## Examples
Expand Down
37 changes: 16 additions & 21 deletions src/pages/docs/react/accessibility.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,13 @@ seo:
template: docs
---






## [Including keyboard users](https://developer.mozilla.org/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_accessibility#including_keyboard_users "Permalink to Including keyboard users")
## [Including keyboard users](https://developer.mozilla.org/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_accessibility#including_keyboard_users 'Permalink to Including keyboard users')

At this point, we've accomplished all of the features we set out to implement. A user can add a new task, check and uncheck tasks, delete tasks, or edit task names. And they can filter their task list by all, active, or completed tasks.

Or, at least: they can do all of these things with a mouse. Unfortunately, these features are not very accessible to keyboard-only users. Let's explore this now.

## [Exploring the keyboard usability problem](https://developer.mozilla.org/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_accessibility#exploring_the_keyboard_usability_problem "Permalink to Exploring the keyboard usability problem")
## [Exploring the keyboard usability problem](https://developer.mozilla.org/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_accessibility#exploring_the_keyboard_usability_problem 'Permalink to Exploring the keyboard usability problem')

Start by clicking on the input at the top of our app, as if you're going to add a new task. 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. Press the Tab key, and you will see the outline appear around the "Add" button beneath the input. This shows you that the browser's focus has moved.

Expand All @@ -35,11 +30,11 @@ When we switch between templates in our `<Todo />` component, we completely remo

To improve the experience for keyboard and screen-reader users, we should manage the browser's focus ourselves.

## [Focusing between templates](https://developer.mozilla.org/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_accessibility#focusing_between_templates "Permalink to Focusing between templates")
## [Focusing between templates](https://developer.mozilla.org/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_accessibility#focusing_between_templates 'Permalink to Focusing between templates')

When a user toggles a `<Todo/>` template from viewing to editing, we should focus on the `<input>` used to rename it; when they toggle back from editing to viewing, we should move focus back to the "Edit" button.

### [Targeting our elements](https://developer.mozilla.org/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_accessibility#targeting_our_elements "Permalink to Targeting our elements")
### [Targeting our elements](https://developer.mozilla.org/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_accessibility#targeting_our_elements 'Permalink to Targeting our elements')

In order to focus on an element in our DOM, we need to tell React which element we want to focus on and how to find it. React's [`useRef`](https://reactjs.org/docs/hooks-reference.html#useref) hook creates an object with a single property: `current`. This property can be a reference to anything we want and look that reference up later. It's particularly useful for referring to DOM elements.

Expand Down Expand Up @@ -84,7 +79,7 @@ The "Edit" button in your view template should read like this:
</button>
```

### [Focusing on our refs with useEffect](https://developer.mozilla.org/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_accessibility#focusing_on_our_refs_with_useeffect "Permalink to Focusing on our refs with useEffect")
### [Focusing on our refs with useEffect](https://developer.mozilla.org/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_accessibility#focusing_on_our_refs_with_useeffect 'Permalink to Focusing on our refs with useEffect')

To use our refs for their intended purpose, we need to import another React hook: [`useEffect()`](https://reactjs.org/docs/hooks-reference.html#useeffect). `useEffect()` is so named because it runs after React renders a given component, and will run any side-effects that we'd like to add to the render process, which we can't run inside the main function body. `useEffect()` is useful in the current situation because we cannot focus on an element until after the `<Todo />` component renders and React knows where our refs are.

Expand Down Expand Up @@ -118,7 +113,7 @@ side effect (3) Todo.js:98

That's it for our experimentation for now. Delete `console.log("main render")` now, and lets move on to implementing our focus management.

### [Focusing on our editing field](https://developer.mozilla.org/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_accessibility#focusing_on_our_editing_field "Permalink to Focusing on our editing field")
### [Focusing on our editing field](https://developer.mozilla.org/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_accessibility#focusing_on_our_editing_field 'Permalink to Focusing on our editing field')

Now that we know our `useEffect()` hook works, we can manage focus with it. As a reminder, we want to focus on the editing field when we switch to the editing template.

Expand All @@ -136,7 +131,7 @@ These changes make it so that, if `isEditing` is true, React reads the current v

Try it now, and you'll see that when you click an "Edit" button, focus moves to the corresponding edit `<input>`!

### [Moving focus back to the edit button](https://developer.mozilla.org/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_accessibility#moving_focus_back_to_the_edit_button "Permalink to Moving focus back to the edit button")
### [Moving focus back to the edit button](https://developer.mozilla.org/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_accessibility#moving_focus_back_to_the_edit_button 'Permalink to Moving focus back to the edit button')

At first glance, getting React to move focus back to our "Edit" button when the edit is saved or cancelled appears deceptively easy. Surely we could add a condition to our `useEffect` to focus on the edit button if `isEditing` is `false`? Let's try it now — update your `useEffect()` call like so:

Expand All @@ -156,7 +151,7 @@ Our `useEffect()` hook is behaving exactly as we designed it: it runs as soon as

We need to refactor our approach so that focus changes only when `isEditing` changes from one value to another.

## [More robust focus management](https://developer.mozilla.org/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_accessibility#more_robust_focus_management "Permalink to More robust focus management")
## [More robust focus management](https://developer.mozilla.org/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_accessibility#more_robust_focus_management 'Permalink to More robust focus management')

In order to meet our refined criteria, we need to know not just the value of `isEditing`, but also _when that value has changed_. In order to do that, we need to be able to read the previous value of the `isEditing` constant. Using pseudocode, our logic should be something like this:

Expand Down Expand Up @@ -207,15 +202,15 @@ Note that the logic of `useEffect()` now depends on `wasEditing`, so we provide

Again try using the "Edit" and "Cancel" buttons to toggle between the templates of your `<Todo />` component; you'll see the browser focus indicator move appropriately, without the problem we discussed at the start of this section.

## [Focusing when the user deletes a task](https://developer.mozilla.org/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_accessibility#focusing_when_the_user_deletes_a_task "Permalink to Focusing when the user deletes a task")
## [Focusing when the user deletes a task](https://developer.mozilla.org/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_accessibility#focusing_when_the_user_deletes_a_task 'Permalink to Focusing when the user deletes a task')

There's one last keyboard experience gap: when a user deletes a task from the list, the focus vanishes. We're going to follow a pattern similar to our previous changes: we'll make a new ref, and utilize our `usePrevious()` hook, so that we can focus on the list heading whenever a user deletes a task.

### [Why the list heading?](https://developer.mozilla.org/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_accessibility#why_the_list_heading "Permalink to Why the list heading?")
### [Why the list heading?](https://developer.mozilla.org/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_accessibility#why_the_list_heading 'Permalink to Why the list heading?')

Sometimes, the place we want to send our focus to is obvious: when we toggled our `<Todo />` templates, we had an origin point to "go back" to — the "Edit" button. In this case however, since we're completely removing elements from the DOM, we have no place to go back to. The next best thing is an intuitive location somewhere nearby. The list heading is our best choice because it's close to the list item the user will delete, and focusing on it will tell the user how many tasks are left.

### [Creating our ref](https://developer.mozilla.org/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_accessibility#creating_our_ref "Permalink to Creating our ref")
### [Creating our ref](https://developer.mozilla.org/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_accessibility#creating_our_ref 'Permalink to Creating our ref')

Import the `useRef()` and `useEffect()` hooks into `App.js` — you'll need them both below:

Expand All @@ -229,7 +224,7 @@ Then declare a new ref inside the `App()` function. Just above the `return` stat
const listHeadingRef = useRef(null);
```

### [Prepare the heading](https://developer.mozilla.org/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_accessibility#prepare_the_heading "Permalink to Prepare the heading")
### [Prepare the heading](https://developer.mozilla.org/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_accessibility#prepare_the_heading 'Permalink to Prepare the heading')

Heading elements like our `<h2>` are not usually focusable. This isn't a problem — we can make any element programmatically focusable by adding the attribute [`tabindex="-1"`](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/tabindex) to it. This means _only focusable with JavaScript_. You can't press Tab to focus on an element with a tabindex of `-1` the same way you could do with a [`<button>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/button) or [`<a>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/a) element (this can be done using `tabindex="0"`, but that's not really appropriate in this case).

Expand All @@ -243,7 +238,7 @@ Let's add the `tabindex` attribute — written as `tabIndex` in JSX — to the h

**Note:** The `tabindex` attribute is great for accessibility edge-cases, but you should take **great care** to not overuse it. Only apply a `tabindex` to an element when you're absolutely sure that making it focusable will benefit your user in some way. In most cases, you should be utilizing elements that can naturally take focus, such as buttons, anchors, and inputs. Irresponsible usage of `tabindex` could have a profoundly negative impact on keyboard and screen-reader users!

### [Getting previous state](https://developer.mozilla.org/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_accessibility#getting_previous_state "Permalink to Getting previous state")
### [Getting previous state](https://developer.mozilla.org/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_accessibility#getting_previous_state 'Permalink to Getting previous state')

We want to focus on the element associated with our ref (via the `ref` attribute) only when our user deletes a task from their list. That's going to require the `usePrevious()` hook we already used earlier on. Add it to the top of your `App.js` file, just below the imports:

Expand All @@ -267,7 +262,7 @@ Here we are invoking `usePrevious()` to track the length of the tasks state, lik

**Note:** Since we're now utilizing `usePrevious()` in two files, a good efficiency refactor would be to move the `usePrevious()` function into its own file, export it from that file, and import it where you need it. Try doing this as an exercise once you've got to the end.

### [Using `useEffect()` to control our heading focus](https://developer.mozilla.org/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_accessibility#using_useeffect_to_control_our_heading_focus "Permalink to Using useEffect() to control our heading focus")
### [Using `useEffect()` to control our heading focus](https://developer.mozilla.org/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_accessibility#using_useeffect_to_control_our_heading_focus 'Permalink to Using useEffect() to control our heading focus')

Now that we've stored how many tasks we previously had, we can set up a `useEffect()` hook to run when our number of tasks changes, which will focus the heading if the number of tasks we have now is less than with it previously was — i.e. we deleted a task!

Expand All @@ -285,10 +280,10 @@ We only try to focus on our list heading if we have fewer tasks now than we did

Now, when you delete a task in your browser, you will see our dashed focus outline appear around the heading above the list.

## [Finished!](https://developer.mozilla.org/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_accessibility#finished! "Permalink to Finished!")
## [Finished!](https://developer.mozilla.org/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_accessibility#finished! 'Permalink to Finished!')

You've just finished building a React app from the ground up! Congratulations! The skills you've learned here will be a great foundation to build on as you continue working with React.

Most of the time, you can be an effective contributor to a React project even if all you do is think carefully about components and their state and props. Remember to always write the best HTML you can.

`useRef()` and `useEffect()` are somewhat advanced features, and you should be proud of yourself for using them! Look out for opportunities to practice them more, because doing so will allow you to create inclusive experiences for users. Remember: our app would have been inaccessible to keyboard users without them!
`useRef()` and `useEffect()` are somewhat advanced features, and you should be proud of yourself for using them! Look out for opportunities to practice them more, because doing so will allow you to create inclusive experiences for users. Remember: our app would have been inaccessible to keyboard users without them!