Welcome to Knowledge Base!

KB at your finger tips

This is one stop global knowledge base where you can learn about all the products, solutions and support features.

Categories
All

Web-React

Lists and Keys – React

Lists and Keys

First, let’s review how you transform lists in JavaScript.


Given the code below, we use the map() function to take an array of numbers and double their values. We assign the new array returned by map() to the variable doubled and log it:


const numbers = [1, 2, 3, 4, 5];
const doubled = numbers.map((number) => number * 2);console.log(doubled);

This code logs [2, 4, 6, 8, 10] to the console.


In React, transforming arrays into lists of elements is nearly identical.


Rendering Multiple Components


You can build collections of elements and include them in JSX using curly braces {} .


Below, we loop through the numbers array using the JavaScript map() function. We return a <li> element for each item. Finally, we assign the resulting array of elements to listItems :


const numbers = [1, 2, 3, 4, 5];
const listItems = numbers.map((number) => <li>{number}</li>);

Then, we can include the entire listItems array inside a <ul> element:


<ul>{listItems}</ul>

Try it on CodePen


This code displays a bullet list of numbers between 1 and 5.


Basic List Component


Usually you would render lists inside a component.


We can refactor the previous example into a component that accepts an array of numbers and outputs a list of elements.


function NumberList(props) {
const numbers = props.numbers;
const listItems = numbers.map((number) => <li>{number}</li> ); return (
<ul>{listItems}</ul> );
}

const numbers = [1, 2, 3, 4, 5];
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<NumberList numbers={numbers} />);

When you run this code, you’ll be given a warning that a key should be provided for list items. A “key” is a special string attribute you need to include when creating lists of elements. We’ll discuss why it’s important in the next section.


Let’s assign a key to our list items inside numbers.map() and fix the missing key issue.


function NumberList(props) {
const numbers = props.numbers;
const listItems = numbers.map((number) =>
<li key={number.toString()}> {number}
</li>
);
return (
<ul>{listItems}</ul>
);
}

Try it on CodePen


Keys


Keys help React identify which items have changed, are added, or are removed. Keys should be given to the elements inside the array to give the elements a stable identity:


const numbers = [1, 2, 3, 4, 5];
const listItems = numbers.map((number) =>
<li key={number.toString()}> {number}
</li>
);

The best way to pick a key is to use a string that uniquely identifies a list item among its siblings. Most often you would use IDs from your data as keys:


const todoItems = todos.map((todo) =>
<li key={todo.id}> {todo.text}
</li>
);

When you don’t have stable IDs for rendered items, you may use the item index as a key as a last resort:


const todoItems = todos.map((todo, index) =>
// Only do this if items have no stable IDs <li key={index}> {todo.text}
</li>
);

We don’t recommend using indexes for keys if the order of items may change. This can negatively impact performance and may cause issues with component state. Check out Robin Pokorny’s article for an in-depth explanation on the negative impacts of using an index as a key. If you choose not to assign an explicit key to list items then React will default to using indexes as keys.


Here is an in-depth explanation about why keys are necessary if you’re interested in learning more.


Extracting Components with Keys


Keys only make sense in the context of the surrounding array.


For example, if you extract a ListItem component, you should keep the key on the <ListItem /> elements in the array rather than on the <li> element in the ListItem itself.


Example: Incorrect Key Usage


function ListItem(props) {
const value = props.value;
return (
// Wrong! There is no need to specify the key here: <li key={value.toString()}> {value}
</li>
);
}

function NumberList(props) {
const numbers = props.numbers;
const listItems = numbers.map((number) =>
// Wrong! The key should have been specified here: <ListItem value={number} /> );
return (
<ul>
{listItems}
</ul>
);
}

Example: Correct Key Usage


function ListItem(props) {
// Correct! There is no need to specify the key here: return <li>{props.value}</li>;}

function NumberList(props) {
const numbers = props.numbers;
const listItems = numbers.map((number) =>
// Correct! Key should be specified inside the array. <ListItem key={number.toString()} value={number} /> );
return (
<ul>
{listItems}
</ul>
);
}

Try it on CodePen


A good rule of thumb is that elements inside the map() call need keys.


Keys Must Only Be Unique Among Siblings


Keys used within arrays should be unique among their siblings. However, they don’t need to be globally unique. We can use the same keys when we produce two different arrays:


function Blog(props) {
const sidebar = ( <ul>
{props.posts.map((post) =>
<li key={post.id}> {post.title}
</li>
)}
</ul>
);
const content = props.posts.map((post) => <div key={post.id}> <h3>{post.title}</h3>
<p>{post.content}</p>
</div>
);
return (
<div>
{sidebar} <hr />
{content} </div>
);
}

const posts = [
{id: 1, title: 'Hello World', content: 'Welcome to learning React!'},
{id: 2, title: 'Installation', content: 'You can install React from npm.'}
];

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<Blog posts={posts} />);

Try it on CodePen


Keys serve as a hint to React but they don’t get passed to your components. If you need the same value in your component, pass it explicitly as a prop with a different name:


const content = posts.map((post) =>
<Post
key={post.id} id={post.id} title={post.title} />

);

With the example above, the Post component can read props.id , but not props.key .


Embedding map() in JSX


In the examples above we declared a separate listItems variable and included it in JSX:


function NumberList(props) {
const numbers = props.numbers;
const listItems = numbers.map((number) => <ListItem key={number.toString()} value={number} /> ); return (
<ul>
{listItems}
</ul>
);
}

JSX allows embedding any expression in curly braces so we could inline the map() result:


function NumberList(props) {
const numbers = props.numbers;
return (
<ul>
{numbers.map((number) => <ListItem key={number.toString()} value={number} /> )} </ul>
);
}

Try it on CodePen


Sometimes this results in clearer code, but this style can also be abused. Like in JavaScript, it is up to you to decide whether it is worth extracting a variable for readability. Keep in mind that if the map() body is too nested, it might be a good time to extract a component.

Is this page useful? Edit this page

Forms – React

Forms

HTML form elements work a bit differently from other DOM elements in React, because form elements naturally keep some internal state. For example, this form in plain HTML accepts a single name:


<form>
<label>
Name:
<input type="text" name="name" />
</label>
<input type="submit" value="Submit" />
</form>

This form has the default HTML form behavior of browsing to a new page when the user submits the form. If you want this behavior in React, it just works. But in most cases, it’s convenient to have a JavaScript function that handles the submission of the form and has access to the data that the user entered into the form. The standard way to achieve this is with a technique called “controlled components”.


Controlled Components


In HTML, form elements such as <input> , <textarea> , and <select> typically maintain their own state and update it based on user input. In React, mutable state is typically kept in the state property of components, and only updated with setState() .


We can combine the two by making the React state be the “single source of truth”. Then the React component that renders a form also controls what happens in that form on subsequent user input. An input form element whose value is controlled by React in this way is called a “controlled component”.


For example, if we want to make the previous example log the name when it is submitted, we can write the form as a controlled component:


class NameForm extends React.Component {
constructor(props) {
super(props);
this.state = {value: ''};
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}

handleChange(event) { this.setState({value: event.target.value}); }
handleSubmit(event) {
alert('A name was submitted: ' + this.state.value);
event.preventDefault();
}

render() {
return (
<form onSubmit={this.handleSubmit}> <label>
Name:
<input type="text" value={this.state.value} onChange={this.handleChange} /> </label>
<input type="submit" value="Submit" />
</form>
);
}
}

Try it on CodePen


Since the value attribute is set on our form element, the displayed value will always be this.state.value , making the React state the source of truth. Since handleChange runs on every keystroke to update the React state, the displayed value will update as the user types.


With a controlled component, the input’s value is always driven by the React state. While this means you have to type a bit more code, you can now pass the value to other UI elements too, or reset it from other event handlers.


The textarea Tag


In HTML, a <textarea> element defines its text by its children:


<textarea>
Hello there, this is some text in a text area
</textarea>

In React, a <textarea> uses a value attribute instead. This way, a form using a <textarea> can be written very similarly to a form that uses a single-line input:


class EssayForm extends React.Component {
constructor(props) {
super(props);
this.state = { value: 'Please write an essay about your favorite DOM element.' };
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}

handleChange(event) { this.setState({value: event.target.value}); }
handleSubmit(event) {
alert('An essay was submitted: ' + this.state.value);
event.preventDefault();
}

render() {
return (
<form onSubmit={this.handleSubmit}>
<label>
Essay:
<textarea value={this.state.value} onChange={this.handleChange} /> </label>
<input type="submit" value="Submit" />
</form>
);
}
}

Notice that this.state.value is initialized in the constructor, so that the text area starts off with some text in it.


The select Tag


In HTML, <select> creates a drop-down list. For example, this HTML creates a drop-down list of flavors:


<select>
<option value="grapefruit">Grapefruit</option>
<option value="lime">Lime</option>
<option selected value="coconut">Coconut</option>
<option value="mango">Mango</option>
</select>

Note that the Coconut option is initially selected, because of the selected attribute. React, instead of using this selected attribute, uses a value attribute on the root select tag. This is more convenient in a controlled component because you only need to update it in one place. For example:


class FlavorForm extends React.Component {
constructor(props) {
super(props);
this.state = {value: 'coconut'};
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}

handleChange(event) { this.setState({value: event.target.value}); }
handleSubmit(event) {
alert('Your favorite flavor is: ' + this.state.value);
event.preventDefault();
}

render() {
return (
<form onSubmit={this.handleSubmit}>
<label>
Pick your favorite flavor:
<select value={this.state.value} onChange={this.handleChange}> <option value="grapefruit">Grapefruit</option>
<option value="lime">Lime</option>
<option value="coconut">Coconut</option>
<option value="mango">Mango</option>
</select>
</label>
<input type="submit" value="Submit" />
</form>
);
}
}

Try it on CodePen


Overall, this makes it so that <input type="text"> , <textarea> , and <select> all work very similarly - they all accept a value attribute that you can use to implement a controlled component.



Note


You can pass an array into the value attribute, allowing you to select multiple options in a select tag:


<select multiple={true} value={['B', 'C']}>


The file input Tag


In HTML, an <input type="file"> lets the user choose one or more files from their device storage to be uploaded to a server or manipulated by JavaScript via the File API.


<input type="file" />

Because its value is read-only, it is an uncontrolled component in React. It is discussed together with other uncontrolled components later in the documentation.


Handling Multiple Inputs


When you need to handle multiple controlled input elements, you can add a name attribute to each element and let the handler function choose what to do based on the value of event.target.name .


For example:


class Reservation extends React.Component {
constructor(props) {
super(props);
this.state = {
isGoing: true,
numberOfGuests: 2
};

this.handleInputChange = this.handleInputChange.bind(this);
}

handleInputChange(event) {
const target = event.target;
const value = target.type === 'checkbox' ? target.checked : target.value;
const name = target.name;
this.setState({
[name]: value });
}

render() {
return (
<form>
<label>
Is going:
<input
name="isGoing" type="checkbox"
checked={this.state.isGoing}
onChange={this.handleInputChange} />

</label>
<br />
<label>
Number of guests:
<input
name="numberOfGuests" type="number"
value={this.state.numberOfGuests}
onChange={this.handleInputChange} />

</label>
</form>
);
}
}

Try it on CodePen


Note how we used the ES6 computed property name syntax to update the state key corresponding to the given input name:


this.setState({
[name]: value});

It is equivalent to this ES5 code:


var partialState = {};
partialState[name] = value;this.setState(partialState);

Also, since setState() automatically merges a partial state into the current state, we only needed to call it with the changed parts.


Controlled Input Null Value


Specifying the value prop on a controlled component prevents the user from changing the input unless you desire so. If you’ve specified a value but the input is still editable, you may have accidentally set value to undefined or null .


The following code demonstrates this. (The input is locked at first but becomes editable after a short delay.)


ReactDOM.createRoot(mountNode).render(<input value="hi" />);

setTimeout(function() {
ReactDOM.createRoot(mountNode).render(<input value={null} />);
}, 1000);

Alternatives to Controlled Components


It can sometimes be tedious to use controlled components, because you need to write an event handler for every way your data can change and pipe all of the input state through a React component. This can become particularly annoying when you are converting a preexisting codebase to React, or integrating a React application with a non-React library. In these situations, you might want to check out uncontrolled components, an alternative technique for implementing input forms.


Fully-Fledged Solutions


If you’re looking for a complete solution including validation, keeping track of the visited fields, and handling form submission, Formik is one of the popular choices. However, it is built on the same principles of controlled components and managing state — so don’t neglect to learn them.

Is this page useful? Edit this page
Read article

Lifting State Up – React

Lifting State Up

Often, several components need to reflect the same changing data. We recommend lifting the shared state up to their closest common ancestor. Let’s see how this works in action.


In this section, we will create a temperature calculator that calculates whether the water would boil at a given temperature.


We will start with a component called BoilingVerdict . It accepts the celsius temperature as a prop, and prints whether it is enough to boil the water:


function BoilingVerdict(props) {
if (props.celsius >= 100) {
return <p>The water would boil.</p>; }
return <p>The water would not boil.</p>;}

Next, we will create a component called Calculator . It renders an <input> that lets you enter the temperature, and keeps its value in this.state.temperature .


Additionally, it renders the BoilingVerdict for the current input value.


class Calculator extends React.Component {
constructor(props) {
super(props);
this.handleChange = this.handleChange.bind(this);
this.state = {temperature: ''}; }

handleChange(e) {
this.setState({temperature: e.target.value}); }

render() {
const temperature = this.state.temperature; return (
<fieldset>
<legend>Enter temperature in Celsius:</legend>
<input value={temperature} onChange={this.handleChange} /> <BoilingVerdict celsius={parseFloat(temperature)} /> </fieldset>
);
}
}

Try it on CodePen


Adding a Second Input


Our new requirement is that, in addition to a Celsius input, we provide a Fahrenheit input, and they are kept in sync.


We can start by extracting a TemperatureInput component from Calculator . We will add a new scale prop to it that can either be "c" or "f" :


const scaleNames = {  c: 'Celsius',  f: 'Fahrenheit'};
class TemperatureInput extends React.Component {
constructor(props) {
super(props);
this.handleChange = this.handleChange.bind(this);
this.state = {temperature: ''};
}

handleChange(e) {
this.setState({temperature: e.target.value});
}

render() {
const temperature = this.state.temperature;
const scale = this.props.scale; return (
<fieldset>
<legend>Enter temperature in {scaleNames[scale]}:</legend> <input value={temperature}
onChange={this.handleChange} />

</fieldset>
);
}
}

We can now change the Calculator to render two separate temperature inputs:


class Calculator extends React.Component {
render() {
return (
<div>
<TemperatureInput scale="c" /> <TemperatureInput scale="f" /> </div>
);
}
}

Try it on CodePen


We have two inputs now, but when you enter the temperature in one of them, the other doesn’t update. This contradicts our requirement: we want to keep them in sync.


We also can’t display the BoilingVerdict from Calculator . The Calculator doesn’t know the current temperature because it is hidden inside the TemperatureInput .


Writing Conversion Functions


First, we will write two functions to convert from Celsius to Fahrenheit and back:


function toCelsius(fahrenheit) {
return (fahrenheit - 32) * 5 / 9;
}

function toFahrenheit(celsius) {
return (celsius * 9 / 5) + 32;
}

These two functions convert numbers. We will write another function that takes a string temperature and a converter function as arguments and returns a string. We will use it to calculate the value of one input based on the other input.


It returns an empty string on an invalid temperature , and it keeps the output rounded to the third decimal place:


function tryConvert(temperature, convert) {
const input = parseFloat(temperature);
if (Number.isNaN(input)) {
return '';
}
const output = convert(input);
const rounded = Math.round(output * 1000) / 1000;
return rounded.toString();
}

For example, tryConvert('abc', toCelsius) returns an empty string, and tryConvert('10.22', toFahrenheit) returns '50.396' .


Lifting State Up


Currently, both TemperatureInput components independently keep their values in the local state:


class TemperatureInput extends React.Component {
constructor(props) {
super(props);
this.handleChange = this.handleChange.bind(this);
this.state = {temperature: ''}; }

handleChange(e) {
this.setState({temperature: e.target.value}); }

render() {
const temperature = this.state.temperature; // ...

However, we want these two inputs to be in sync with each other. When we update the Celsius input, the Fahrenheit input should reflect the converted temperature, and vice versa.


In React, sharing state is accomplished by moving it up to the closest common ancestor of the components that need it. This is called “lifting state up”. We will remove the local state from the TemperatureInput and move it into the Calculator instead.


If the Calculator owns the shared state, it becomes the “source of truth” for the current temperature in both inputs. It can instruct them both to have values that are consistent with each other. Since the props of both TemperatureInput components are coming from the same parent Calculator component, the two inputs will always be in sync.


Let’s see how this works step by step.


First, we will replace this.state.temperature with this.props.temperature in the TemperatureInput component. For now, let’s pretend this.props.temperature already exists, although we will need to pass it from the Calculator in the future:


  render() {
// Before: const temperature = this.state.temperature;
const temperature = this.props.temperature; // ...

We know that props are read-only. When the temperature was in the local state, the TemperatureInput could just call this.setState() to change it. However, now that the temperature is coming from the parent as a prop, the TemperatureInput has no control over it.


In React, this is usually solved by making a component “controlled”. Just like the DOM <input> accepts both a value and an onChange prop, so can the custom TemperatureInput accept both temperature and onTemperatureChange props from its parent Calculator .


Now, when the TemperatureInput wants to update its temperature, it calls this.props.onTemperatureChange :


  handleChange(e) {
// Before: this.setState({temperature: e.target.value});
this.props.onTemperatureChange(e.target.value); // ...


Note:


There is no special meaning to either temperature or onTemperatureChange prop names in custom components. We could have called them anything else, like name them value and onChange which is a common convention.



The onTemperatureChange prop will be provided together with the temperature prop by the parent Calculator component. It will handle the change by modifying its own local state, thus re-rendering both inputs with the new values. We will look at the new Calculator implementation very soon.


Before diving into the changes in the Calculator , let’s recap our changes to the TemperatureInput component. We have removed the local state from it, and instead of reading this.state.temperature , we now read this.props.temperature . Instead of calling this.setState() when we want to make a change, we now call this.props.onTemperatureChange() , which will be provided by the Calculator :


class TemperatureInput extends React.Component {
constructor(props) {
super(props);
this.handleChange = this.handleChange.bind(this);
}

handleChange(e) {
this.props.onTemperatureChange(e.target.value); }

render() {
const temperature = this.props.temperature; const scale = this.props.scale;
return (
<fieldset>
<legend>Enter temperature in {scaleNames[scale]}:</legend>
<input value={temperature}
onChange={this.handleChange} />

</fieldset>
);
}
}

Now let’s turn to the Calculator component.


We will store the current input’s temperature and scale in its local state. This is the state we “lifted up” from the inputs, and it will serve as the “source of truth” for both of them. It is the minimal representation of all the data we need to know in order to render both inputs.


For example, if we enter 37 into the Celsius input, the state of the Calculator component will be:


{
temperature: '37',
scale: 'c'
}

If we later edit the Fahrenheit field to be 212, the state of the Calculator will be:


{
temperature: '212',
scale: 'f'
}

We could have stored the value of both inputs but it turns out to be unnecessary. It is enough to store the value of the most recently changed input, and the scale that it represents. We can then infer the value of the other input based on the current temperature and scale alone.


The inputs stay in sync because their values are computed from the same state:


class Calculator extends React.Component {
constructor(props) {
super(props);
this.handleCelsiusChange = this.handleCelsiusChange.bind(this);
this.handleFahrenheitChange = this.handleFahrenheitChange.bind(this);
this.state = {temperature: '', scale: 'c'}; }

handleCelsiusChange(temperature) {
this.setState({scale: 'c', temperature}); }

handleFahrenheitChange(temperature) {
this.setState({scale: 'f', temperature}); }

render() {
const scale = this.state.scale; const temperature = this.state.temperature; const celsius = scale === 'f' ? tryConvert(temperature, toCelsius) : temperature; const fahrenheit = scale === 'c' ? tryConvert(temperature, toFahrenheit) : temperature;
return (
<div>
<TemperatureInput
scale="c"
temperature={celsius} onTemperatureChange={this.handleCelsiusChange} />
<TemperatureInput
scale="f"
temperature={fahrenheit} onTemperatureChange={this.handleFahrenheitChange} />
<BoilingVerdict
celsius={parseFloat(celsius)} />
</div>
);
}
}

Try it on CodePen


Now, no matter which input you edit, this.state.temperature and this.state.scale in the Calculator get updated. One of the inputs gets the value as is, so any user input is preserved, and the other input value is always recalculated based on it.


Let’s recap what happens when you edit an input:



  • React calls the function specified as onChange on the DOM <input> . In our case, this is the handleChange method in the TemperatureInput component.

  • The handleChange method in the TemperatureInput component calls this.props.onTemperatureChange() with the new desired value. Its props, including onTemperatureChange , were provided by its parent component, the Calculator .

  • When it previously rendered, the Calculator had specified that onTemperatureChange of the Celsius TemperatureInput is the Calculator ’s handleCelsiusChange method, and onTemperatureChange of the Fahrenheit TemperatureInput is the Calculator ’s handleFahrenheitChange method. So either of these two Calculator methods gets called depending on which input we edited.

  • Inside these methods, the Calculator component asks React to re-render itself by calling this.setState() with the new input value and the current scale of the input we just edited.

  • React calls the Calculator component’s render method to learn what the UI should look like. The values of both inputs are recomputed based on the current temperature and the active scale. The temperature conversion is performed here.

  • React calls the render methods of the individual TemperatureInput components with their new props specified by the Calculator . It learns what their UI should look like.

  • React calls the render method of the BoilingVerdict component, passing the temperature in Celsius as its props.

  • React DOM updates the DOM with the boiling verdict and to match the desired input values. The input we just edited receives its current value, and the other input is updated to the temperature after conversion.


Every update goes through the same steps so the inputs stay in sync.


Lessons Learned


There should be a single “source of truth” for any data that changes in a React application. Usually, the state is first added to the component that needs it for rendering. Then, if other components also need it, you can lift it up to their closest common ancestor. Instead of trying to sync the state between different components, you should rely on the top-down data flow.


Lifting state involves writing more “boilerplate” code than two-way binding approaches, but as a benefit, it takes less work to find and isolate bugs. Since any state “lives” in some component and that component alone can change it, the surface area for bugs is greatly reduced. Additionally, you can implement any custom logic to reject or transform user input.


If something can be derived from either props or state, it probably shouldn’t be in the state. For example, instead of storing both celsiusValue and fahrenheitValue , we store just the last edited temperature and its scale . The value of the other input can always be calculated from them in the render() method. This lets us clear or apply rounding to the other field without losing any precision in the user input.


When you see something wrong in the UI, you can use React Developer Tools to inspect the props and move up the tree until you find the component responsible for updating the state. This lets you trace the bugs to their source:


Monitoring State in React DevTools
Is this page useful? Edit this page
Read article

Composition vs Inheritance – React

Composition vs Inheritance

React has a powerful composition model, and we recommend using composition instead of inheritance to reuse code between components.


In this section, we will consider a few problems where developers new to React often reach for inheritance, and show how we can solve them with composition.


Containment


Some components don’t know their children ahead of time. This is especially common for components like Sidebar or Dialog that represent generic “boxes”.


We recommend that such components use the special children prop to pass children elements directly into their output:


function FancyBorder(props) {
return (
<div className={'FancyBorder FancyBorder-' + props.color}>
{props.children} </div>
);
}

This lets other components pass arbitrary children to them by nesting the JSX:


function WelcomeDialog() {
return (
<FancyBorder color="blue">
<h1 className="Dialog-title"> Welcome </h1> <p className="Dialog-message"> Thank you for visiting our spacecraft! </p> </FancyBorder>
);
}

Try it on CodePen


Anything inside the <FancyBorder> JSX tag gets passed into the FancyBorder component as a children prop. Since FancyBorder renders {props.children} inside a <div> , the passed elements appear in the final output.


While this is less common, sometimes you might need multiple “holes” in a component. In such cases you may come up with your own convention instead of using children :


function SplitPane(props) {
return (
<div className="SplitPane">
<div className="SplitPane-left">
{props.left} </div>
<div className="SplitPane-right">
{props.right} </div>
</div>
);
}

function App() {
return (
<SplitPane
left={
<Contacts /> }

right={
<Chat /> }
/>

);
}

Try it on CodePen


React elements like <Contacts /> and <Chat /> are just objects, so you can pass them as props like any other data. This approach may remind you of “slots” in other libraries but there are no limitations on what you can pass as props in React.


Specialization


Sometimes we think about components as being “special cases” of other components. For example, we might say that a WelcomeDialog is a special case of Dialog .


In React, this is also achieved by composition, where a more “specific” component renders a more “generic” one and configures it with props:


function Dialog(props) {
return (
<FancyBorder color="blue">
<h1 className="Dialog-title">
{props.title} </h1>
<p className="Dialog-message">
{props.message} </p>
</FancyBorder>
);
}

function WelcomeDialog() {
return (
<Dialog title="Welcome" message="Thank you for visiting our spacecraft!" /> );
}

Try it on CodePen


Composition works equally well for components defined as classes:


function Dialog(props) {
return (
<FancyBorder color="blue">
<h1 className="Dialog-title">
{props.title}
</h1>
<p className="Dialog-message">
{props.message}
</p>
{props.children} </FancyBorder>
);
}

class SignUpDialog extends React.Component {
constructor(props) {
super(props);
this.handleChange = this.handleChange.bind(this);
this.handleSignUp = this.handleSignUp.bind(this);
this.state = {login: ''};
}

render() {
return (
<Dialog title="Mars Exploration Program"
message="How should we refer to you?">

<input value={this.state.login} onChange={this.handleChange} /> <button onClick={this.handleSignUp}> Sign Me Up! </button> </Dialog>
);
}

handleChange(e) {
this.setState({login: e.target.value});
}

handleSignUp() {
alert(`Welcome aboard, ${this.state.login}!`);
}
}

Try it on CodePen


So What About Inheritance?


At Facebook, we use React in thousands of components, and we haven’t found any use cases where we would recommend creating component inheritance hierarchies.


Props and composition give you all the flexibility you need to customize a component’s look and behavior in an explicit and safe way. Remember that components may accept arbitrary props, including primitive values, React elements, or functions.


If you want to reuse non-UI functionality between components, we suggest extracting it into a separate JavaScript module. The components may import it and use that function, object, or class, without extending it.

Is this page useful? Edit this page
Read article

Thinking in React – React

Thinking in React

React is, in our opinion, the premier way to build big, fast Web apps with JavaScript. It has scaled very well for us at Facebook and Instagram.


One of the many great parts of React is how it makes you think about apps as you build them. In this document, we’ll walk you through the thought process of building a searchable product data table using React.


Start With A Mock


Imagine that we already have a JSON API and a mock from our designer. The mock looks like this:





Mockup



Our JSON API returns some data that looks like this:


[
{category: "Sporting Goods", price: "$49.99", stocked: true, name: "Football"},
{category: "Sporting Goods", price: "$9.99", stocked: true, name: "Baseball"},
{category: "Sporting Goods", price: "$29.99", stocked: false, name: "Basketball"},
{category: "Electronics", price: "$99.99", stocked: true, name: "iPod Touch"},
{category: "Electronics", price: "$399.99", stocked: false, name: "iPhone 5"},
{category: "Electronics", price: "$199.99", stocked: true, name: "Nexus 7"}
];

Step 1: Break The UI Into A Component Hierarchy


The first thing you’ll want to do is to draw boxes around every component (and subcomponent) in the mock and give them all names. If you’re working with a designer, they may have already done this, so go talk to them! Their Photoshop layer names may end up being the names of your React components!


But how do you know what should be its own component? Use the same techniques for deciding if you should create a new function or object. One such technique is the single responsibility principle, that is, a component should ideally only do one thing. If it ends up growing, it should be decomposed into smaller subcomponents.


Since you’re often displaying a JSON data model to a user, you’ll find that if your model was built correctly, your UI (and therefore your component structure) will map nicely. That’s because UI and data models tend to adhere to the same information architecture . Separate your UI into components, where each component matches one piece of your data model.





Diagram showing nesting of components



You’ll see here that we have five components in our app. We’ve italicized the data each component represents. The numbers in the image correspond to the numbers below.



  1. FilterableProductTable (orange): contains the entirety of the example

  2. SearchBar (blue): receives all user input

  3. ProductTable (green): displays and filters the data collection based on user input

  4. ProductCategoryRow (turquoise): displays a heading for each category

  5. ProductRow (red): displays a row for each product


If you look at ProductTable , you’ll see that the table header (containing the “Name” and “Price” labels) isn’t its own component. This is a matter of preference, and there’s an argument to be made either way. For this example, we left it as part of ProductTable because it is part of rendering the data collection which is ProductTable ’s responsibility. However, if this header grows to be complex (e.g., if we were to add affordances for sorting), it would certainly make sense to make this its own ProductTableHeader component.


Now that we’ve identified the components in our mock, let’s arrange them into a hierarchy. Components that appear within another component in the mock should appear as a child in the hierarchy:




  • FilterableProductTable



    • SearchBar


    • ProductTable



      • ProductCategoryRow

      • ProductRow






Step 2: Build A Static Version in React


See the Pen Thinking In React: Step 2 on CodePen.



Now that you have your component hierarchy, it’s time to implement your app. The easiest way is to build a version that takes your data model and renders the UI but has no interactivity. It’s best to decouple these processes because building a static version requires a lot of typing and no thinking, and adding interactivity requires a lot of thinking and not a lot of typing. We’ll see why.


To build a static version of your app that renders your data model, you’ll want to build components that reuse other components and pass data using props . props are a way of passing data from parent to child. If you’re familiar with the concept of state , don’t use state at all to build this static version. State is reserved only for interactivity, that is, data that changes over time. Since this is a static version of the app, you don’t need it.


You can build top-down or bottom-up. That is, you can either start with building the components higher up in the hierarchy (i.e. starting with FilterableProductTable ) or with the ones lower in it ( ProductRow ). In simpler examples, it’s usually easier to go top-down, and on larger projects, it’s easier to go bottom-up and write tests as you build.


At the end of this step, you’ll have a library of reusable components that render your data model. The components will only have render() methods since this is a static version of your app. The component at the top of the hierarchy ( FilterableProductTable ) will take your data model as a prop. If you make a change to your underlying data model and call root.render() again, the UI will be updated. You can see how your UI is updated and where to make changes. React’s one-way data flow (also called one-way binding ) keeps everything modular and fast.


Refer to the React docs if you need help executing this step.


A Brief Interlude: Props vs State


There are two types of “model” data in React: props and state. It’s important to understand the distinction between the two; skim the official React docs if you aren’t sure what the difference is. See also FAQ: What is the difference between state and props?


Step 3: Identify The Minimal (but complete) Representation Of UI State


To make your UI interactive, you need to be able to trigger changes to your underlying data model. React achieves this with state .


To build your app correctly, you first need to think of the minimal set of mutable state that your app needs. The key here is DRY: Don’t Repeat Yourself . Figure out the absolute minimal representation of the state your application needs and compute everything else you need on-demand. For example, if you’re building a TODO list, keep an array of the TODO items around; don’t keep a separate state variable for the count. Instead, when you want to render the TODO count, take the length of the TODO items array.


Think of all the pieces of data in our example application. We have:



  • The original list of products

  • The search text the user has entered

  • The value of the checkbox

  • The filtered list of products


Let’s go through each one and figure out which one is state. Ask three questions about each piece of data:



  1. Is it passed in from a parent via props? If so, it probably isn’t state.

  2. Does it remain unchanged over time? If so, it probably isn’t state.

  3. Can you compute it based on any other state or props in your component? If so, it isn’t state.


The original list of products is passed in as props, so that’s not state. The search text and the checkbox seem to be state since they change over time and can’t be computed from anything. And finally, the filtered list of products isn’t state because it can be computed by combining the original list of products with the search text and value of the checkbox.


So finally, our state is:



  • The search text the user has entered

  • The value of the checkbox


Step 4: Identify Where Your State Should Live


See the Pen Thinking In React: Step 4 on CodePen.


OK, so we’ve identified what the minimal set of app state is. Next, we need to identify which component mutates, or owns , this state.


Remember: React is all about one-way data flow down the component hierarchy. It may not be immediately clear which component should own what state. This is often the most challenging part for newcomers to understand, so follow these steps to figure it out:


For each piece of state in your application:



  • Identify every component that renders something based on that state.

  • Find a common owner component (a single component above all the components that need the state in the hierarchy).

  • Either the common owner or another component higher up in the hierarchy should own the state.

  • If you can’t find a component where it makes sense to own the state, create a new component solely for holding the state and add it somewhere in the hierarchy above the common owner component.


Let’s run through this strategy for our application:



  • ProductTable needs to filter the product list based on state and SearchBar needs to display the search text and checked state.

  • The common owner component is FilterableProductTable .

  • It conceptually makes sense for the filter text and checked value to live in FilterableProductTable


Cool, so we’ve decided that our state lives in FilterableProductTable . First, add an instance property this.state = {filterText: '', inStockOnly: false} to FilterableProductTable ’s constructor to reflect the initial state of your application. Then, pass filterText and inStockOnly to ProductTable and SearchBar as a prop. Finally, use these props to filter the rows in ProductTable and set the values of the form fields in SearchBar .


You can start seeing how your application will behave: set filterText to "ball" and refresh your app. You’ll see that the data table is updated correctly.


Step 5: Add Inverse Data Flow


See the Pen Thinking In React: Step 5 on CodePen.


So far, we’ve built an app that renders correctly as a function of props and state flowing down the hierarchy. Now it’s time to support data flowing the other way: the form components deep in the hierarchy need to update the state in FilterableProductTable .


React makes this data flow explicit to help you understand how your program works, but it does require a little more typing than traditional two-way data binding.


If you try to type or check the box in the previous version of the example (step 4), you’ll see that React ignores your input. This is intentional, as we’ve set the value prop of the input to always be equal to the state passed in from FilterableProductTable .


Let’s think about what we want to happen. We want to make sure that whenever the user changes the form, we update the state to reflect the user input. Since components should only update their own state, FilterableProductTable will pass callbacks to SearchBar that will fire whenever the state should be updated. We can use the onChange event on the inputs to be notified of it. The callbacks passed by FilterableProductTable will call setState() , and the app will be updated.


And That’s It


Hopefully, this gives you an idea of how to think about building components and applications with React. While it may be a little more typing than you’re used to, remember that code is read far more often than it’s written, and it’s less difficult to read this modular, explicit code. As you start to build large libraries of components, you’ll appreciate this explicitness and modularity, and with code reuse, your lines of code will start to shrink. :)

Is this page useful? Edit this page
Read article

Accessibility – React

Accessibility

Why Accessibility?


Web accessibility (also referred to as a11y ) is the design and creation of websites that can be used by everyone. Accessibility support is necessary to allow assistive technology to interpret web pages.


React fully supports building accessible websites, often by using standard HTML techniques.


Standards and Guidelines


WCAG


The Web Content Accessibility Guidelines provides guidelines for creating accessible web sites.


The following WCAG checklists provide an overview:



  • WCAG checklist from Wuhcag

  • WCAG checklist from WebAIM

  • Checklist from The A11Y Project


WAI-ARIA


The Web Accessibility Initiative - Accessible Rich Internet Applications document contains techniques for building fully accessible JavaScript widgets.


Note that all aria-* HTML attributes are fully supported in JSX. Whereas most DOM properties and attributes in React are camelCased, these attributes should be hyphen-cased (also known as kebab-case, lisp-case, etc) as they are in plain HTML:


<input
type="text"
aria-label={labelText} aria-required="true" onChange={onchangeHandler}
value={inputValue}
name="name"
/>

Semantic HTML


Semantic HTML is the foundation of accessibility in a web application. Using the various HTML elements to reinforce the meaning of information
in our websites will often give us accessibility for free.



  • MDN HTML elements reference


Sometimes we break HTML semantics when we add <div> elements to our JSX to make our React code work, especially when working with lists ( <ol> , <ul> and <dl> ) and the HTML <table> .
In these cases we should rather use React Fragments to group together multiple elements.


For example,


import React, { Fragment } from 'react';
function ListItem({ item }) {
return (
<Fragment> <dt>{item.term}</dt>
<dd>{item.description}</dd>
</Fragment> );
}

function Glossary(props) {
return (
<dl>
{props.items.map(item => (
<ListItem item={item} key={item.id} />
))}
</dl>
);
}

You can map a collection of items to an array of fragments as you would any other type of element as well:


function Glossary(props) {
return (
<dl>
{props.items.map(item => (
// Fragments should also have a `key` prop when mapping collections
<Fragment key={item.id}> <dt>{item.term}</dt>
<dd>{item.description}</dd>
</Fragment> ))}
</dl>
);
}

When you don’t need any props on the Fragment tag you can use the short syntax, if your tooling supports it:


function ListItem({ item }) {
return (
<> <dt>{item.term}</dt>
<dd>{item.description}</dd>
</> );
}

For more info, see the Fragments documentation.


Accessible Forms


Labeling


Every HTML form control, such as <input> and <textarea> , needs to be labeled accessibly. We need to provide descriptive labels that are also exposed to screen readers.


The following resources show us how to do this:



  • The W3C shows us how to label elements

  • WebAIM shows us how to label elements

  • The Paciello Group explains accessible names


Although these standard HTML practices can be directly used in React, note that the for attribute is written as htmlFor in JSX:


<label htmlFor="namedInput">Name:</label><input id="namedInput" type="text" name="name"/>

Notifying the user of errors


Error situations need to be understood by all users. The following link shows us how to expose error texts to screen readers as well:



  • The W3C demonstrates user notifications

  • WebAIM looks at form validation


Focus Control


Ensure that your web application can be fully operated with the keyboard only:



  • WebAIM talks about keyboard accessibility


Keyboard focus and focus outline


Keyboard focus refers to the current element in the DOM that is selected to accept input from the keyboard. We see it everywhere as a focus outline similar to that shown in the following image:







Blue keyboard focus outline around a selected link.





Only ever use CSS that removes this outline, for example by setting outline: 0 , if you are replacing it with another focus outline implementation.


Mechanisms to skip to desired content


Provide a mechanism to allow users to skip past navigation sections in your application as this assists and speeds up keyboard navigation.


Skiplinks or Skip Navigation Links are hidden navigation links that only become visible when keyboard users interact with the page. They are very easy to implement with internal page anchors and some styling:



  • WebAIM - Skip Navigation Links


Also use landmark elements and roles, such as <main> and <aside> , to demarcate page regions as assistive technology allow the user to quickly navigate to these sections.


Read more about the use of these elements to enhance accessibility here:



  • Accessible Landmarks


Programmatically managing focus


Our React applications continuously modify the HTML DOM during runtime, sometimes leading to keyboard focus being lost or set to an unexpected element. In order to repair this, we need to programmatically nudge the keyboard focus in the right direction. For example, by resetting keyboard focus to a button that opened a modal window after that modal window is closed.


MDN Web Docs takes a look at this and describes how we can build keyboard-navigable JavaScript widgets.


To set focus in React, we can use Refs to DOM elements.


Using this, we first create a ref to an element in the JSX of a component class:


class CustomTextInput extends React.Component {
constructor(props) {
super(props);
// Create a ref to store the textInput DOM element this.textInput = React.createRef(); }
render() {
// Use the `ref` callback to store a reference to the text input DOM // element in an instance field (for example, this.textInput). return (
<input
type="text"
ref={this.textInput} />

);
}
}

Then we can focus it elsewhere in our component when needed:


focus() {
// Explicitly focus the text input using the raw DOM API
// Note: we're accessing "current" to get the DOM node
this.textInput.current.focus();
}

Sometimes a parent component needs to set focus to an element in a child component. We can do this by exposing DOM refs to parent components through a special prop on the child component that forwards the parent’s ref to the child’s DOM node.


function CustomTextInput(props) {
return (
<div>
<input ref={props.inputRef} /> </div>
);
}

class Parent extends React.Component {
constructor(props) {
super(props);
this.inputElement = React.createRef(); }
render() {
return (
<CustomTextInput inputRef={this.inputElement} /> );
}
}

// Now you can set focus when required.
this.inputElement.current.focus();

When using a HOC to extend components, it is recommended to forward the ref to the wrapped component using the forwardRef function of React. If a third party HOC does not implement ref forwarding, the above pattern can still be used as a fallback.


A great focus management example is the react-aria-modal. This is a relatively rare example of a fully accessible modal window. Not only does it set initial focus on
the cancel button (preventing the keyboard user from accidentally activating the success action) and trap keyboard focus inside the modal, it also resets focus back to the element that initially triggered the modal.



Note:


While this is a very important accessibility feature, it is also a technique that should be used judiciously. Use it to repair the keyboard focus flow when it is disturbed, not to try and anticipate how
users want to use applications.



Mouse and pointer events


Ensure that all functionality exposed through a mouse or pointer event can also be accessed using the keyboard alone. Depending only on the pointer device will lead to many cases where keyboard users cannot use your application.


To illustrate this, let’s look at a prolific example of broken accessibility caused by click events. This is the outside click pattern, where a user can disable an opened popover by clicking outside the element.


A toggle button opening a popover list implemented with the click outside pattern and operated with a mouse showing that the close action works.

This is typically implemented by attaching a click event to the window object that closes the popover:


class OuterClickExample extends React.Component {
constructor(props) {
super(props);

this.state = { isOpen: false };
this.toggleContainer = React.createRef();

this.onClickHandler = this.onClickHandler.bind(this);
this.onClickOutsideHandler = this.onClickOutsideHandler.bind(this);
}

componentDidMount() { window.addEventListener('click', this.onClickOutsideHandler); }
componentWillUnmount() {
window.removeEventListener('click', this.onClickOutsideHandler);
}

onClickHandler() {
this.setState(currentState => ({
isOpen: !currentState.isOpen
}));
}

onClickOutsideHandler(event) { if (this.state.isOpen && !this.toggleContainer.current.contains(event.target)) { this.setState({ isOpen: false }); } }
render() {
return (
<div ref={this.toggleContainer}>
<button onClick={this.onClickHandler}>Select an option</button>
{this.state.isOpen && (
<ul>
<li>Option 1</li>
<li>Option 2</li>
<li>Option 3</li>
</ul>
)}
</div>
);
}
}

This may work fine for users with pointer devices, such as a mouse, but operating this with the keyboard alone leads to broken functionality when tabbing to the next element as the window object never receives a click event. This can lead to obscured functionality which blocks users from using your application.


A toggle button opening a popover list implemented with the click outside pattern and operated with the keyboard showing the popover not being closed on blur and it obscuring other screen elements.

The same functionality can be achieved by using appropriate event handlers instead, such as onBlur and onFocus :


class BlurExample extends React.Component {
constructor(props) {
super(props);

this.state = { isOpen: false };
this.timeOutId = null;

this.onClickHandler = this.onClickHandler.bind(this);
this.onBlurHandler = this.onBlurHandler.bind(this);
this.onFocusHandler = this.onFocusHandler.bind(this);
}

onClickHandler() {
this.setState(currentState => ({
isOpen: !currentState.isOpen
}));
}

// We close the popover on the next tick by using setTimeout. // This is necessary because we need to first check if // another child of the element has received focus as // the blur event fires prior to the new focus event. onBlurHandler() { this.timeOutId = setTimeout(() => { this.setState({ isOpen: false }); }); }
// If a child receives focus, do not close the popover. onFocusHandler() { clearTimeout(this.timeOutId); }
render() {
// React assists us by bubbling the blur and // focus events to the parent. return (
<div onBlur={this.onBlurHandler} onFocus={this.onFocusHandler}> <button onClick={this.onClickHandler}
aria-haspopup="true"
aria-expanded={this.state.isOpen}>

Select an option
</button>
{this.state.isOpen && (
<ul>
<li>Option 1</li>
<li>Option 2</li>
<li>Option 3</li>
</ul>
)}
</div>
);
}
}

This code exposes the functionality to both pointer device and keyboard users. Also note the added aria-* props to support screen-reader users. For simplicity’s sake the keyboard events to enable arrow key interaction of the popover options have not been implemented.


A popover list correctly closing for both mouse and keyboard users.

This is one example of many cases where depending on only pointer and mouse events will break functionality for keyboard users. Always testing with the keyboard will immediately highlight the problem areas which can then be fixed by using keyboard aware event handlers.


More Complex Widgets


A more complex user experience should not mean a less accessible one. Whereas accessibility is most easily achieved by coding as close to HTML as possible, even the most complex widget can be coded accessibly.


Here we require knowledge of ARIA Roles as well as ARIA States and Properties.
These are toolboxes filled with HTML attributes that are fully supported in JSX and enable us to construct fully accessible, highly functional React components.


Each type of widget has a specific design pattern and is expected to function in a certain way by users and user agents alike:



  • ARIA Authoring Practices Guide (APG) - Design Patterns and Examples

  • Heydon Pickering - ARIA Examples

  • Inclusive Components


Other Points for Consideration


Setting the language


Indicate the human language of page texts as screen reader software uses this to select the correct voice settings:



  • WebAIM - Document Language


Setting the document title


Set the document <title> to correctly describe the current page content as this ensures that the user remains aware of the current page context:



  • WCAG - Understanding the Document Title Requirement


We can set this in React using the React Document Title Component.


Color contrast


Ensure that all readable text on your website has sufficient color contrast to remain maximally readable by users with low vision:



  • WCAG - Understanding the Color Contrast Requirement

  • Everything About Color Contrast And Why You Should Rethink It

  • A11yProject - What is Color Contrast


It can be tedious to manually calculate the proper color combinations for all cases in your website so instead, you can calculate an entire accessible color palette with Colorable.


Both the aXe and WAVE tools mentioned below also include color contrast tests and will report on contrast errors.


If you want to extend your contrast testing abilities you can use these tools:



  • WebAIM - Color Contrast Checker

  • The Paciello Group - Color Contrast Analyzer


Development and Testing Tools


There are a number of tools we can use to assist in the creation of accessible web applications.


The keyboard


By far the easiest and also one of the most important checks is to test if your entire website can be reached and used with the keyboard alone. Do this by:



  1. Disconnecting your mouse.

  2. Using Tab and Shift+Tab to browse.

  3. Using Enter to activate elements.

  4. Where required, using your keyboard arrow keys to interact with some elements, such as menus and dropdowns.


Development assistance


We can check some accessibility features directly in our JSX code. Often intellisense checks are already provided in JSX aware IDE’s for the ARIA roles, states and properties. We also have access to the following tool:


eslint-plugin-jsx-a11y


The eslint-plugin-jsx-a11y plugin for ESLint provides AST linting feedback regarding accessibility issues in your JSX. Many IDE’s allow you to integrate these findings directly into code analysis and source code windows.


Create React App has this plugin with a subset of rules activated. If you want to enable even more accessibility rules, you can create an .eslintrc file in the root of your project with this content:


{
"extends": ["react-app", "plugin:jsx-a11y/recommended"],
"plugins": ["jsx-a11y"]
}

Testing accessibility in the browser


A number of tools exist that can run accessibility audits on web pages in your browser. Please use them in combination with other accessibility checks mentioned here as they can only
test the technical accessibility of your HTML.


aXe, aXe-core and react-axe


Deque Systems offers aXe-core for automated and end-to-end accessibility tests of your applications. This module includes integrations for Selenium.


The Accessibility Engine or aXe, is an accessibility inspector browser extension built on aXe-core .


You can also use the @axe-core/react module to report these accessibility findings directly to the console while developing and debugging.


WebAIM WAVE


The Web Accessibility Evaluation Tool is another accessibility browser extension.


Accessibility inspectors and the Accessibility Tree


The Accessibility Tree is a subset of the DOM tree that contains accessible objects for every DOM element that should be exposed
to assistive technology, such as screen readers.


In some browsers we can easily view the accessibility information for each element in the accessibility tree:



  • Using the Accessibility Inspector in Firefox

  • Using the Accessibility Inspector in Chrome

  • Using the Accessibility Inspector in OS X Safari


Screen readers


Testing with a screen reader should form part of your accessibility tests.


Please note that browser / screen reader combinations matter. It is recommended that you test your application in the browser best suited to your screen reader of choice.


Commonly Used Screen Readers


NVDA in Firefox


NonVisual Desktop Access or NVDA is an open source Windows screen reader that is widely used.


Refer to the following guides on how to best use NVDA:



  • WebAIM - Using NVDA to Evaluate Web Accessibility

  • Deque - NVDA Keyboard Shortcuts


VoiceOver in Safari


VoiceOver is an integrated screen reader on Apple devices.


Refer to the following guides on how to activate and use VoiceOver:



  • WebAIM - Using VoiceOver to Evaluate Web Accessibility

  • Deque - VoiceOver for OS X Keyboard Shortcuts

  • Deque - VoiceOver for iOS Shortcuts


JAWS in Internet Explorer


Job Access With Speech or JAWS, is a prolifically used screen reader on Windows.


Refer to the following guides on how to best use JAWS:



  • WebAIM - Using JAWS to Evaluate Web Accessibility

  • Deque - JAWS Keyboard Shortcuts


Other Screen Readers


ChromeVox in Google Chrome


ChromeVox is an integrated screen reader on Chromebooks and is available as an extension for Google Chrome.


Refer to the following guides on how best to use ChromeVox:



  • Google Chromebook Help - Use the Built-in Screen Reader

  • ChromeVox Classic Keyboard Shortcuts Reference

Is this page useful? Edit this page
Read article