Categories
JavaScript React

Creating Accessible React Apps — Mouse Events and Other Things

React is a library for creating front end views. It has a big ecosystem of libraries that work with it. Also, we can use it to enhance existing apps.

In this article, we’ll look at how to create accessible React apps.

Mouse and Pointer Events

Any functionality that’s exposed through a mouse or pointer event should also be accessible using the keyboard alone.

We should use onBlur and onFocus on buttons, if we’re using them to toggle something on or off.

For example, we should write:

class App extends React.Component {  
  constructor(props) {  
    super(props);  
    this.state = { open: false };  
  } 

  handleClick() {  
    this.setState({ open: true });  
  } 

  handleFocus() {  
    this.setState({ open: true });  
  } 

  handleBlur() {  
    setTimeout(() => {  
      this.setState({ open: false });  
    });  
  } 

  render() {  
    return (  
      <div  
        onFocus={this.handleFocus.bind(this)}  
        onBlur={this.handleBlur.bind(this)}  
        aria-expanded={this.state.open}  
      >  
        <button onClick={this.handleClick.bind(this)}>Menu</button>  
        {this.state.open && (  
          <ul>  
            <li>Apple</li>  
            <li>Orange</li>  
            <li>Mengo</li>  
          </ul>  
        )}  
      </div>  
    );  
  }  
}

In the code above, we have the handlers for blur and focus events handlers attached to the wrapper div.

Also, we have the aria-expanded attribute to indicate whether the div has an expanded menu.

When we press the tab button to focus on the button, we can toggle the menu without the mouse. This is what we want since not everyone can use a mouse or another pointing device.

More Complex Widgets

We should put in HTML aria attributes so that our components are accessible to React components.

This is even more important for complex components since they have many parts.

Setting the Language

We should set the language of the page so that screen reader software can use it to set the right voice settings.

Setting the Document Title

The title text should correctly describe the current page so that users are aware of the page’s content.

Color Contrast

Elements should have enough contrast so that they can be readable by viewers with low vision.

We can calculate color combinations with enough contrast by using the Colorable package.

Testing The Keyboard

We should test if everything can navigate to with only the keyboard.

To do this, we can press Tab and Shift+Tab to navigate forward and backward respectively.

Also, we should be able to use the Enter key to activate elements.

Arrow keys should work with menus and dropdowns.

eslint-plugin-jsx-a11y

ESLint has a plugin to check for accessibility issues in JSX code. Many IDE integrate with this directly.

It an NPM package so that we can install it by running:

npm install eslint --save-dev

We can install the package and put in the following to the .eslintrc file of our project as follows:

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

Testing Accessibility in the Browser

We can test for accessibility by using the aXe-core package for automated testing of accessibility.

Screen Readers

Screen readers should be able to read the page correctly. Common screen readers include NVDA, VoiceOver, and JAWS.

There’s also a ChromeVox extension for Google Chrome.

Conclusion

There’re many aspects to consider to make React apps accessible. We should set the language, title, and aria attributes correctly.

Also, elements on a page should be accessible via the keyboard.

We can use ESLint plugins and automated testing tools to test accessibility.

Categories
JavaScript React

Type Checking With React PropTypes

React is a library for creating front end views. It has a big ecosystem of libraries that work with it. Also, we can use it to enhance existing apps.

In this article, we’ll look at how to valid prop data types by using PropTypes .

Type Checking With PropType

As our code grows, we can catch a lot of bugs with type checking.

React has built-in type checking abilities for props.

We can add prop type checks as follows:

import React from "react";  
import ReactDOM from "react-dom";  
import PropTypes from "prop-types";

class Greeting extends React.Component {  
  render() {  
    return <p>Hello, {this.props.name}</p>;  
  }  
}

Greeting.propTypes = {  
  name: PropTypes.string  
};

class App extends React.Component {  
  render() {  
    return <Greeting name="Jane" />;  
  }  
}

In the code above, we have:

Greeting.propTypes = {  
  name: PropTypes.string  
};

to check that the name prop passed in is a string.

In addition to strings, it has many other kinds of validations that can be used to make sure that data received is valid.

When an invalid value is provided for a prop, a warning will be shown in the JavaScript console.

Prop type checks are only run in development mode for performance reasons.

PropTypes

In addition to strings, there’re many more prop types available. They’re the following:

  • PropTypes.array — checks for arrays
  • PropTypes.bool — checks for boolean
  • PropTypes.func — checks for functions
  • PropTypes.number — checks for number
  • PropTypes.object — checks for object
  • PropTypes.string — checks for string
  • PropTypes.symbol — checks for symbol
  • PropTypes.node — checks for anything that can be rendered
  • PropTypes.element — checks for a React element
  • PropTypes.elementType — checks for a React element type (e.g. Component )
  • PropTypes.instanceOf(Foo) — checks for instance of a class, in this case, Foo
  • PropTypes.oneOf([‘foo’, ‘bar’]) — checks for one of the values in the array
  • PropTypes.oneOfType([PropTypes.string, PropTypes.number]) — checks for one of the types in the array
  • PropTypes.arrayOf(PropTypes.number) — checks for an array of the given type
  • PropTypes.shape({color: PropTypes.string, fontSize: PropTypes.number } — checks for an object with these properties and types of values
  • PropTypes.exact({ name: PropTypes.string, quantity: PropTypes.number }) — checks for an object with these properties and types of values with warnings on extra properties
  • isRequired — set a prop as being required, e.g. we can use is by writing PropTypes.func.isRequired to make a prop that takes a function required.

We can also set our own prop validation function as follows:

class Greeting extends React.Component {  
  render() {  
    return <p>Hello, {this.props.name}</p>;  
  }  
}

Greeting.propTypes = {  
  name(props, propName, componentName) {  
    if (!["Jane", "Joe"].includes(props[propName])) {  
      throw new Error("Invalid name");  
    }  
  }  
};

class App extends React.Component {  
  render() {  
    return <Greeting name="Foo" />;  
  }  
}

In the code above, we have:

Greeting.propTypes = {  
  name(props, propName, componentName) {  
    if (!["Jane", "Joe"].includes(props[propName])) {  
      throw new Error("Invalid name");  
    }  
  }  
};

which has the name function where we can check the name prop to see if it’s set to 'Jane' or 'Joe' .

If it’s not, like the example above, we’ll get the warning:

Warning: Failed prop type: Invalid name

in the JavaScript console.

Requiring Single Child

We can specify that only a single child can be passed to a component as children.

To do this, we write:

class Greeting extends React.Component {  
  render() {  
    return <p>Hello, {this.props.children}</p>;  
  }  
}

Greeting.propTypes = {  
  children: PropTypes.element.isRequired  
};

class App extends React.Component {  
  render() {  
    return <Greeting>Jane</Greeting>;  
  }  
}

In the code above, we specified that children has the type PropTypes.element.isRequired , which means that we check if only one element is passed in.

Default Prop Values

We can also set default values for props.

For instance, we can write:

class Greeting extends React.Component {  
  render() {  
    return <p>Hello, {this.props.name}</p>;  
  }  
}

Greeting.defaultProps = {  
  name: "Jane"  
};

class App extends React.Component {  
  render() {  
    return <Greeting />;  
  }  
}

In the code above, we have the defaultProps property set for Greeting to set the default props.

Since we didn’t pass any value for the name prop to Greeting , React will set the name prop to 'Jane' by default, so we get Hello, Jane.

If we change 'Jane' to 'Joe' , then we get Hello, Joe instead.

Conclusion

We can use prop types to check the types for our props. This prevents us from passing in data that we don’t want, preventing potential bugs.

Prop types can check for many types, including any JavaScript type, like numbers, objects, and symbols.

It can also check the structure of objects and arrays, and also checks if specific values are passed in.

In addition, we can make our own validator function to check what they’re and throw an error to reject invalid values.

We can add prop type check for children to validate what’s passed in between tags.

Also, we can set a default value for props, by setting a value for it in the defaultProps object.

Finally, we can use isRequired to check for if a prop value is passed in.

Categories
JavaScript React

Sharing State with the React Context API

React is a library for creating front end views. It has a big ecosystem of libraries that work with it. Also, we can use it to enhance existing apps.

React components can only pass data from parent to child via props. The Context API adds to that by allowing components with other relationships to share data.

In this article, we’ll look at how to use it to share data between components.

When to Use Context

We should use Context to share data between React components. However, it should be used sparingly since it creates tight coupling between components.

To use it within a simple app, we can write the following:

const ColorContext = React.createContext("green");

class Button extends React.Component {  
  render() {  
    return (  
      <div>  
        <ColorContext.Consumer>  
          {value => (  
            <button style={{ color: value }}>{this.props.children}</button>  
          )}  
        </ColorContext.Consumer>  
      </div>  
    );  
  }  
}

class App extends React.Component {  
  render() {  
    return (  
      <div>  
        <ColorContext.Provider value="blue">  
          <Button>Click Me</Button>  
        </ColorContext.Provider>  
      </div>  
    );  
  }  
}

In the code above, we created a Context to share data by writing:

const ColorContext = React.createContext("green");

createContext takes a default value as an argument, where we passed in 'green' .

Then in the App component, we have the ColorContext.Provider component with the value prop set to the value that we want to share.

In the example above, it’ll be 'blue' . We wrapped it around the components that we want to share the data with so that we can access the value from that component.

In this case, we created a new Button component, which has the ColorContext.Consumer component. Inside it, we can get the value shared from the context provider from the value parameter in the function we inserted inside the ColorContext.Consumer component.

value should be set to 'blue' since that’s what we set as the value of the value prop.

Inside the function we passed in the consumer, we returned a buttom element with the style prop and we set the color style to value , which is 'blue' .

Alternatives to Context

If we want to pass data into a deeply nested component, we can instead pass in the whole component down to where we want it. This way, we don’t have to worry about passing props to multiple levels to pass something that’s only needed by deeply nested components.

For example, if we want to pass the color prop to Button components, which is contained in a ButtonBar . We can do that as follows:

class Button extends React.Component {  
  render() {  
    return (  
      <button style={{ color: this.props.color }}>{this.props.children}</button>  
    );  
  }  
}

class ButtonBar extends React.Component {  
  render() {  
    return this.props.buttons;  
  }  
}

class App extends React.Component {  
  render() {  
    const buttons = [  
      <Button color="blue">Click Me</Button>,  
      <Button color="green">Click Me 2</Button>  
    ];  
    return <ButtonBar buttons={buttons} />;  
  }  
}

In the App component, we have the Button components in the buttons array. Then we passed the whole array straight down to the ButtonBar component.

Then ButtonBar just returns what we passed in, which is this.props.buttons .

This also means more complexity in the higher-order components, so it may not be suitable in all cases.

Updating Context from a Nested Component

We can pass in functions to the object that we pass into createContext so that we can call them inside the component that has the context consumer component.

For example, we can write the following:

const colorObj = {  
  color: "green",  
  toggleColor: () => {}  
};

const ColorContext = React.createContext(colorObj);  
class Button extends React.Component {  
  render() {  
    return (  
      <div>  
        <ColorContext.Consumer>  
          {({ color, toggleColor }) => (  
            <button onClick={toggleColor} style={{ color }}>  
              {this.props.children}  
            </button>  
          )}  
        </ColorContext.Consumer>  
      </div>  
    );  
  }  
}

class App extends React.Component {  
  constructor(props) {  
    super(props);  
    this.state = {  
      color: "blue",  
      toggleColor: () => {  
        this.setState(state => ({  
          color: state.color === "green" ? "blue" : "green"  
        }));  
      }  
    };  
  } 

  render() {  
    return (  
      <div>  
        <ColorContext.Provider value={this.state}>  
          <Button>Click Me</Button>  
        </ColorContext.Provider>  
      </div>  
    );  
  }  
}

The code above starts with defining the colorObj object, which is passed into createContext as the default value of ColorContext .

Then in the App component, we initialize this.state by setting it to an object with the toggleColor function, and the color property set to 'blue' .

We pass this.state as the value of the value prop of ColorContext.Provider .

Then we access the whole object inside the ColorContext.Consumer component in the Button component.

Inside there, we get the color and toggleColor property from the this.state which we passed in from the ColorContext.Provider . Then we pass toggleColor into the onClick prop, and color into the object that we passed into the style prop.

Then when we click the Click Me button, the text color will toggle between blue and green.

Consuming Multiple Contexts

We can consume multiple contexts by nesting them. For example, we can do that as follows:

const ColorContext = React.createContext("green");  
const BorderContext = React.createContext("");
class Button extends React.Component {  
  render() {  
    return (  
      <div>  
        <ColorContext.Consumer>  
          {color => (  
            <BorderContext.Consumer>  
              {border => (  
                <button style={{ color, border }}>{this.props.children}</button>  
              )}  
            </BorderContext.Consumer>  
          )}  
        </ColorContext.Consumer>  
      </div>  
    );  
  }  
}

class App extends React.Component {  
  render() {  
    return (  
      <div>  
        <ColorContext.Provider value="blue">  
          <BorderContext.Provider value="3px solid green">  
            <Button>Click Me</Button>  
          </BorderContext.Provider>  
        </ColorContext.Provider>  
      </div>  
    );  
  }  
}

In the code above, we create 2 Contexts, ColorContext and BorderContext and passed in values to the value prop to both. We nested the providers in the App component, which means that both contexts can be consumed by the Button component inside.

Then in the Button component, we have consumers for both contexts nested in each other. And then we can get both values that were passed in from the providers.

We then use both values to set the styles of the button .

In the end, we a button with blue text and a thick green border.

Conclusion

We can use the React Context API to share data between components.

It works by creating a Context object with React.createContext . Then we wrap the context provider component outside the components that we want to consume the context from.

Then in the component that we put inside the provider, we have the context consumer component wrapped outside of whatever we want to apply the context value to.

Finally, we can get the value inside the function that we pass inside the Context consumer.

Categories
JavaScript React

Using React Strict Mode to Avoid Deprecated Code and Side Effects

React is a library for creating front end views. It has a big ecosystem of libraries that work with it. Also, we can use it to enhance existing apps.

In this article, we’ll look at how to use React’s strict mode to get extra warnings about deprecated APIs and side effects during development.

Strict Mode

Strict mode is a tool for highlighting potential problems in an application. It doesn’t render any visible UI.

It’s only used to activate additional checks and warnings for its descendants.

Strict mode doesn’t affect the production build.

We can add strict mode to a React app as follows:

class App extends React.Component {  
  render() {  
    return (  
      <div>  
        <p>foo</p>  
        <React.StrictMode>  
          <p>bar</p>  
        </React.StrictMode>  
      </div>  
    );  
  }  
}

In the code above, the p tag with ‘foo’ isn’t checked by strict mode since it’s outside of the React.StrictMode component, but the p element inside is checked by strict mode.

Identifying Unsafe Lifecycles

Strict mode checks for unsafe lifecycles. Some lifecycle methods are being deprecated because they encourage unsafe coding practices.

They are:

  • componentWillMount
  • componentWillReceiveProps
  • componentWillUpdate

The UNSAFE_ prefix will be added in an upcoming release.

2 new lifecycle methods are replacing the ones above. They’re the static getDerivedStateFromProps and getSnapshotBeforeUpdate methods.

getSnapshotBeforeUpdate lifecycle is called before mutations are made, and the return value of it will be passed as the 3rd parameter to componentDidUpdate .

getSnapshotBeforeUpdate and componentDidUpdate together covers all the user cases for componentWillUpdate .

Strict mode will warn about the deprecation of old lifecycle hooks.

Warning About Legacy String ref API Usage

Also, React strict mode will warn about using string refs in our code.

String refs are deprecated because they can’t be statically typed. They need to always be consistent. Magic dynamic strings break optimizations in VMs, and it only works on one level.

We can’t pass it around like callback and object refs.

Therefore, it’ll warn us about the usage of string refs since they’re deprecated.

Callback refs and createRef are both supported in the future.

Warning About Deprecated findDOMNode Usage

The findDOMNode method is deprecated. We can use it to search for a DOM node given a class instance.

We shouldn’t need to do this because we can attach a ref to a DOM node.

findDOMNode only returns the first child, but it’s possible for a component to render multiple DOM levels with the use of Fragments.

Therefore, it isn’t very useful now since it only searches one level and we can use ref to get the exact element we’re looking for.

We can attach a ref to the wrapper element instead:

class App extends React.Component {  
  constructor(props) {  
    super(props);  
    this.wrapper = React.createRef();  
  }  
  render() {  
    return <div ref={this.wrapper}>{this.props.children}</div>;  
  }  
}

If we don’t want to wrapper div to be rendered, we can set display: contents in our CSS if we don’t want the node to be part of the layout.

Detecting Unexpected Side Effects

React works in 2 phases:

  • The render phase makes any changes to the DOM. React calls render during this phase and then compares the result to the previous render.
  • The commit phase runs any lifecycle methods to apply any changes required.

Render phase lifecycles include the following class component methods:

  • constructor
  • componentWillMount
  • componentWillReceiveProps
  • componentWillUpdate
  • getDerivedStateFromProps
  • shouldComponentUpdate
  • render
  • setState

Since they may be called more than once, they shouldn’t commit any side effects. Ignoring this rule may lead to problems like memory leaks and invalid app state.

Strict mode checks if side effects are made by running the following methods twice:

  • Class component constructor method
  • The render method
  • setState
  • The static getDerivedStateFromProps lifecycle

Detecting Legacy Context API

Strict mode will detect uses of the old Context API. It’ll be removed in future versions. We should move to the new one if it’s used.

Conclusion

We can use strict mode to detect uses of deprecated lifecycle methods, legacy Context API, string refs, and some code that commits unexpected side effects.

It only shows warnings in development and doesn’t affect production code.

Categories
JavaScript React

State and Lifecycle of React Components

React is a library for creating front end views. It has a big ecosystem of libraries that work with it. Also, we can use it to enhance existing apps.

In this article, we’ll look at the lifecycle of React components and how to change their internal state.

Changing Internal State

Props are immutable since we want to keep React components pure with respect to props. This means that when we pass in the same props, we always get the same output assuming nothing else changes.

This isn’t very useful in most cases since we want to change things inside a component.

To do this, we can manipulate the internal state of a component.

All class-based React components have internal state accessible via this.state, and we can change it by calling this.setState.

For example, if we want to create a Clock component that shows the current time and updates it every second, we can do that as follows:

class Clock extends React.Component {  
  constructor(props) {  
    super(props);  
    this.state = { date: new Date(), timer: undefined };  
  } 

  componentWillMount() {  
    this.updateDate();  
  } 

  componentWillUnmount() {  
    clearInterval(this.state.timer);  
  } 

  updateDate() {  
    const timer = setInterval(() => {  
      this.setState({ date: new Date() });  
    }, 1000);  
    this.setState({ timer });  
  } 

  render() {  
    return (  
      <div>  
        <p>It is {this.state.date.toLocaleTimeString()}.</p>  
      </div>  
    );  
  }  
}

In the code above, we declared a class Clock that extends React.Component. This means the code is a React component, which can have its own lifecycle methods and the render method.

Inside the Clock component, we declared the state field in the constructor which has the initial state date, and a timer state to hold the timer object that’s returned by setInterval.

Also, we called super(props) since Clock extends React.Component, and the React.Constructor takes props as an argument.

Then we have our componentDidMount lifecycle hook to load the initialization code when the Clock component is mounted into the DOM.

The updateDate method is called in componentDidMount to continuously update the this.state.date every second.

To update the date inside the setInterval callback, we called this.setState with an object inside.

The object has the state’s name as the key as we defined it in the first line, and the value is the new value that we want to set the state to.

We also called setState to set the timer field so that we can call clearInterval with it inside the componentWillUnmount. The componentWillUnmount hook is called when the component is removed from the DOM.

It’s a good place to run any code that’s used to clean things up.

Finally, in the render method, we render the date. This method is called whenever this.state changes by calling this.setState, so if we put this.state properties in there, the latest value of it will always be shown.

This means that this.state.date will be the latest date after:

this.setState({ date: new Date() });

is called.

componentDidMount and componentWillUnmount are lifecycle methods. They’re called only in specific parts of a React component’s lifecycle.

this.setState is asynchronous, so we shouldn’t assume that code that’s listed after a this.setstate call will run immediately after this.setState.

To mount it in the DOM, we call the ReactDOM.render method with Clock passed in as follows:

import React from "react";  
import ReactDOM from "react-dom";

class Clock extends React.Component {  
  constructor(props) {  
    super(props);  
    this.state = { date: new Date(), timer: undefined };  
  } 

  componentWillMount() {  
    this.updateDate();  
  } 

  componentWillUnmount() {  
    clearInterval(this.state.timer);  
  } 

  updateDate() {  
    const timer = setInterval(() => {  
      this.setState({ date: new Date() });  
    }, 1000);  
    this.setState({ timer });  
  } 

  render() {  
    return (  
      <div>  
        <p>It is {this.state.date.toLocaleTimeString()}.</p>  
      </div>  
    );  
  }  
}

const rootElement = document.getElementById("root");  
ReactDOM.render(<Clock />, rootElement);

Using State Correctly

We should never modify the state directly because it won’t trigger a re-rendering of a component.

So we shouldn’t write:

this.state.foo = 'bar';

Instead, we should always use this.setState as follows:

this.setState({foo: 'bar'});

State Updates May Be Asynchronous

State updates are asynchronous, so we shouldn’t depend on it run one after the other.

Also, we can’t just combine props and state values within setState .

For example, the following may fail:

this.setState({  
  count: this.state.count + this.props.increment,  
});

Instead, we write:

this.setState((state, props) => ({  
  count: state.count + props.increment  
}));

to get the latest values from props to update the code.

Regular and arrow functions both work, so we can also write:

this.setState(function(state, props) {  
  return {  
    count: state.count + props.increment  
  };  
});

State Updates are Merged

When we call setState, React merges the object that we pass into setState into the current state.

For example, if we have 2 states, firstName and lastName, then when we called this.setstate({ lastName });, this.state.firstName stays intact, while this.state.lastName is updated with the latest value of lastName.

Data Flows Down

States are always inside a component, and it can be passed down to child components and elements as props.

React apps has a unidirectional data flow that goes from parent to child.

Conclusion

We can create a React component that is dynamic by storing states inside a component.

The state object is stored in the state field of the React component class.

We can set the state by running this.setState.

React components have lifecycles that trigger methods in the React component class. These are called lifecycle hooks.

We can use them to run code at certain stages of a React component’s lifecycle.