Categories
JavaScript React

Using the React State Hook

React is a library for creating frontend 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 the state hook to keep dynamic states in a function component.

Using the State Hook

We can use the React.useState method to create a state with a corresponding function to change the state.

For example, we can write the following code to add a hook to our app:

import React from "react";  
import ReactDOM from "react-dom";
function App() {  
  const[count, setCount] = React.useState(0); 
  return (  
    <div>  
      <button onClick={() => setCount(count + 1)}>Count {count}</button>  
    </div>  
  );  
}

In the code above, we have the React.useState hook with the default 0 passed in. It returns an array with the state, which we called count, and a function to set the state, which is called setCount.

Then in the onClick handler of the button, we can the setCount function to update the count.

Equivalent Class Example

The example above would be the same as the following class:

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

  render() {  
    return (  
      <div>  
        <button onClick={() => this.setState({ count: this.state.count + 1 })}>  
          Count: {this.state.count}  
        </button>  
      </div>  
    );  
  }  
}

In the code above, we have this.state initialized in the constructor with count 0. Then in the button we pass in a click event handler that calls setState to update the count state by incrementing it by 1.

Therefore, this.setState({ count: this.state.count + 1 }) is the same as setCount(count + 1) and count is the same as this.state.count.

Hooks and Function Components

A function component looks like:

const App = props => <p>foo</p>;

or:

function App(props) {  
  return <p>foo</p>;  
}

They were previously known as stateless components. However, now that React has hooks, they can keep their own state. Therefore, they should be called function components.

What’s a Hook?

A hook is a special function that lets us hook into React features. useState in the example above is a hook that lets us add React state to function components.

Declaring a State Variable

useState declares a state variable. In the example above, we have a variable called count but we can call it anything else.

useState has the same capabilities as this.state that we had in a class.

Variables disappear when the function exists but state variables are preserved by React.

The only argument for useState is the initial state. The state doesn’t have to be an object unlike classes.

We can have any type of data as the initial state.

If we want to store multiple values in state, then we’ll call useState for each kind of data.

useState always gives us the current state. It’s not only for creating the initial state.

Reading State

In the example, that we had:

import React from "react";  
import ReactDOM from "react-dom";
function App() {  
  const [count, setCount] = React.useState(0); 
  return (  
    <div>  
      <button onClick={() => setCount(count + 1)}>Count {count}</button>  
    </div>  
  );  
}

We get the current state from count returned by useState .

Updating State

Instead of calling this.setState like we do in class components, we call the setCount function directly.

Therefore, we don’t have to worry about the value of this .

What Do Square Brackets Mean?

The square brackets in:

const [count, setCount] = React.useState(0);

is the destructuring assignment operation, which means that values from an array are assigned to variables depending on the position.

The first element is assigned to the first variable, the second is assigned to the second variable, etc.

const [count, setCount] = React.useState(0);

is the same as:

const countState = React.useState(0);  
const count = countState[0];  
const setCount = countState[1];

Using Multiple State Variables

We will call useState as many times as we need to use multiple state variables.

For example, we can write:

function App() {  
  const [count, setCount = React.useState(0);  
  const [foo] = React.useState({ text: "bar" });  
  return (  
    <div>  
      <button onClick={() => setCount(count + 1)}>Count {count}</button>  
      <p>{foo.text}</p>  
    </div>  
  );

In the code above, we have 2 calls to useState to create 2 states, count and foo .

States can have object values, so we don’t have to create too many states.

Conclusion

We can use the useState hook to get and set dynamic states in a function component.

It returns the current state and a function to update the state in an array.

Then we can use them directly to display data and call the returned function to update the state.

Categories
JavaScript React

Manipulate DOM Elements in External React Components with ForwardRef

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

To manipulate DOM elements directly with React, we can create a ref, associate it to an element, and then reference that and call its methods to manipulate the DOM item directly.

In this article, we’ll look at how to pass the ref to components outside of its originating component by forwarding refs.

Forwarding refs to DOM components

We can forward refs by creating a ref and then call the forwardRef method to get the ref and then pass it into any place we want.

For example, if we have a Button component that returns a button element, and we want to get the button element from the outside component, we can write the following:

const Button = React.forwardRef((props, ref) => (  
  <button id="custom-button" ref={ref}>  
    {props.children}  
  </button>  
));

class App extends React.Component {  
  constructor(props) {  
    super(props);  
    this.state = {};  
    this.buttonRef = React.createRef();  
  } componentDidMount() {  
    this.buttonRef.current.focus();  
  } render() {  
    return <Button ref={this.buttonRef}>Click Me</Button>;  
  }  
}

In the code above, we have a Button component created by using the React.forwardRef method with a callback passed in.

The callback has a props parameter which has the props that are passed in from the parent component, and the ref object which has the ref that’s passed in from the parent component.

Then we set the ref prop of the button element to the ref from the parameter.

Then we can create a new ref in the App component by calling React.createRef in App ‘s constructor. Then we pass that into the ref prop of Button so that we can access the ForwardRef from the button element.

This means the this.buttonRef is referencing the button element because we passed it into Button , which passes this.buttonRef into the button element via the callback we passed into React.forwardRef .

Then in the App component, we call:

this.buttonRef.current.focus();

in componentDidMount to focus the button in Button from App .

Forwarding refs in Higher-Order Components

We can also forward refs in high-order components. To do this, we write something like the following:

const Button = ({ forwardedRef, children }) => (  
  <button ref={forwardedRef}>{children}</button>  
);

function logProps(Component) {  
  class LogProps extends React.Component {  
    componentDidMount() {  
      console.log(this.props);  
    } 

    render() {  
      const { forwardedRef, ...rest } = this.props;  
      return <Component forwardedRef={forwardedRef} {...rest} />;  
    }  
  } 

  return React.forwardRef((props, ref) => {  
    return <LogProps {...props} forwardedRef={ref} />;  
  });  
}

class App extends React.Component {  
  constructor(props) {  
    super(props);  
    this.buttonRef = React.createRef();  
  } 

  componentDidMount() {  
    this.buttonRef.current.focus();  
  } 

  render() {  
    const ButtonLogProp = logProps(Button);  
    return <ButtonLogProp ref={this.buttonRef}>Click Me</ButtonLogProp>;  
  }  
}

In the code above, we have the logProps higher-order component. The logProps component takes a Component .

logProps return a component with the forwarded refs passed in by calling React.forwardRef with a callback that returns LogProps .

In the App component we pass this.buttonRef as the value to ButtonLogProp .

ButtonLogProp is created by calling logProps with the Button component passed in. This means Component is Button in logProp .

Component, which is Button is then returned in the render method of the LogProp component.

At the end of the logProp higher-order component, we return the component with returned from React.forwardRef . The callback we pass into forwardRef returns the LogProps component with the props including the forwarded ref passed in.

All the props will then reach the Button component, which sets the ref of the button element to the this.buttonRef , which is first passed into logProp , then passed into LogProp , and React.forwardRef returns a component with the forwarded ref passed to the Button component, and then into the button element.

In other words, we passed the ref from App , to logProp , to LogProp , then forwarded with React.forwardRef to Button and then to button .

Conclusion

We can use refs from external components by forwarding refs. This lets us manipulate DOM elements from external components within a component.

Forwarding refs also works with higher-order components. All we have to do is to return the component we want to return in the higher-order component in the React.forwardRef callback with the forwarded ref passed in.

Categories
JavaScript React

Introduction to React Hooks

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 hooks to make function components smarter.

Introducing Hooks

Hooks are introduced with React 16.8.

We can use hooks to make function components keep and change dynamic states.

For example, we can write the following code to add a hook to our app:

import React from "react";  
import ReactDOM from "react-dom";
function App() {  
  const [count, setCount] = React.useState(0); 
  return (  
    <div>  
      <button onClick={() => setCount(count + 1)}>Count {count}</button>  
    </div>  
  );  
}

In the code above, we have the React.useState hook with the default 0 passed in. It returns an array with the state, which we called count , and a function to set the state, which is called setCount .

Then in the onClick handler of the button, we can the setCount function to update the count.

Other packages like React DOM also has to be updated to 16.8 or later.

React Native since 0.59 also supports hooks.

No Breaking Changes

Hooks are completely opt-in. They coexist with class components. Therefore, we don’t have to change any existing code. They’re also completely interoperable with class components.

Class components will be available in the future. They also don’t replace our knowledge of existing React concepts.

Why do we need Hooks

We can use gooks to reuse stateful logic without creating higher-order components or doing other things to change our component hierarchy.

Complex Components Become Hard to Understand

Complex components have many methods which are lifecycle hooks and also our own user-defined functions.

They all have a mix of unrelated logic. This makes it too easy to introduce bugs and inconsistencies.

It’s impossible to break them into smaller components because stateful logic is everywhere. It’s also hard to test them because of the complexity.

We can use hooks to split one component into smaller functions based on what’s related.

Classes are Confusing

We have to understand a lot about how JavaScript classes work, which is different from most languages since JavaScript classes are just syntactic sugar on top of its own prototypical inheritance model.

Also, we have to make sure the value of this is correct so we don’t introduce errors.

Classes can introduce patterns that make optimizations difficult. They don’t minify well and they make hot reloading flaky and unreliable.

Hooks are used without classes, so we don’t have to worry about any of these issues.

Gradual Adoption Strategy

We can create new components with hooks without affecting anything existing code.

Therefore, we can try them on non-critical parts of an app first.

Class components will be supported in the foreseeable future.

Conclusion

Hooks are the new way to keep dynamic states in function components.

We can use function components with hooks the same way that we write class components.

They coexist with existing class components and they’ll still be supported in the foreseeable future.

Hooks remove the confusion that arises from JavaScript classes and also let React minify the code by providing additional optimizations that can’t be done with classes.

Categories
JavaScript React

Creating Accessible React Apps — Focus and Semantics

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.

Why Accessibility?

We should create accessible apps so that they can be used by everyone.

Standards and Guidelines

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

Also, we have the Web Accessibility Initiative — Accessible Rich Internet Applications document contains guidelines for building fully accessible JavaScript widgets.

aria-* HTML attributes are fully supported in JSX. These attributes are kept as kebab-case as they’re in HTML.

Semantic HTML

HTML tags are named for their meanings. This means that they make sense for screen readers and other accessibility programs that parse web content.

This means that instead of using div to group elements, we should use Fragments instead so that our app doesn’t have extra div elements getting in the way of screen readers.

For example, we can add fragments to a component as follows:

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

class App extends React.Component {  
  constructor(props) {  
    super(props);  
    this.state = {  
      items: [  
        { term: "coffee", meaning: "black drink" },  
        { term: "milk", meaning: "white drink" }  
      ]  
    };  
  } 

  render() {  
    return (  
      <dl>  
        {this.state.items.map(item => (  
          <ListItem item={item} key={item.id} />  
        ))}  
      </dl>  
    );  
  }  
}

Then we get the following HTML rendered:

<dl>  
  <dt>coffee</dt>  
  <dd>black drink</dd>  
  <dt>milk</dt>  
  <dd>white drink</dd>  
</dl>

As we can see, fragments do not produce any extra HTML but let us group elements together.

A shorthand or fragments are <> and </> . Therefore, we can rewrite the code above as follows:

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

We keep the rest of the code the same.

Then we get the same HTML rendered.

Accessible Forms

We should label forms to provide accessibility for all users.

To do this, we add a for attribute to label elements. In React, the for element represented by the htmlFor prop.

This applies to all form controls.

For example, we can do the following to add a htmlFor prop:

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

  render() {  
    return (  
      <>  
        <label htmlFor="name">Name:</label>  
        <input type="text" name="name" value={this.state.name} />  
      </>  
    );  
  }  
}

In the code above, we have:

htmlFor="name"

to relate the label to the form field. The htmlFor value should be the same as the name value of the form control element.

The full accessibility guidelines are at:

Notifying the user of errors

Errors need to understood by users. The following guides tells us how to expose error text to screen readers:

Focus Control

We should only change or remove outlines by using CSS so that users can get the focused element even without seeing the outline.

Ways to Skip to Desired Content

Also, we should provide ways for users to skip to what they want to see or use.

We can implement that with internal page anchors and some styling.

We can also put important content in elements like main and aside so that they can be differentiated from other content.

Programmatically Managing Focus

In React, we can access DOM elements by using refs. This means that we can control when an element is in focus by calling DOM methods to focus an element.

For example, if we want to focus an element when the component is mounted in the DOM tree, we can call focus as follows:

class App extends React.Component {  
  constructor(props) {  
    super(props);  
    this.textInput = React.createRef();  
  } 

  componentDidMount() {  
    this.textInput.current.focus();  
  } 

  render() {  
    return <input type="text" ref={this.textInput} />;  
  }  
}

In the code above, we created a ref to access the DOM element by writing:

this.textInput = React.createRef();

In the input element, we have:

ref={this.textInput}

to associate the input element with the ref we created.

Then in the componentDidMount hook, we have:

this.textInput.current.focus();

to focus the input when the component mounts. this.textInput.current returns the input element, so that we can call the native focus method on it.

Conclusion

When creating React apps, we should have accessibility in mind.

This means that we should use semantic HTML tags so that all users can understand what a page has.

Also, we should provide ways for users to skip to the content that they want to see.

Finally, we can focus elements programmatically so that users can use inputs right away when focus is lost by regaining focus.

Categories
JavaScript React

Using Uncontrolled Components in React Apps

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 uncontrolled components in React code.

Uncontrolled Components

Uncontrolled components are where we use the DOM properties to manipulate form inputs.

We can use a ref to get form values directly from the DOM.

For example, we can write the following:

class App extends React.Component {  
  constructor(props) {  
    super(props);  
    this.input = React.createRef();  
  } 

  handleSubmit(event) {  
    alert(`Name submitted: ${this.input.current.value}`);  
    event.preventDefault();  
  } 

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

In the code above we created the this.input ref in the constructor and attached it to the input element.

Then when we type in something and click Submit, we get whatever we typed into the input box displayed in the alert box since we accessed it with this.input.current.value .

This makes integrating React and non-React code easier since we’re using the DOM to get the value.

Default Values

The value attribute on form elements will override the value in the DOM.

With an uncontrolled component, we often want to specify the initial value and leave subsequent updates uncontrolled.

We can set the defaultValue attribute to do this:

class App extends React.Component {  
  constructor(props) {  
    super(props);  
    this.input = React.createRef();  
  } 

  handleSubmit(event) {  
    alert(`Name submitted: ${this.input.current.value}`);  
    event.preventDefault();  
  } 

  render() {  
    return (  
      <form onSubmit={this.handleSubmit.bind(this)}>  
        <label>  
          Name:  
          <input type="text" defaultValue="Foo" ref={this.input} />  
        </label>  
        <input type="submit" value="Submit" />  
      </form>  
    );  
  }  
}

In the code above, we set the defaultValue attribute to Foo , which is the value of this.input.current.value if we don’t change the input value.

The file input Tag

File inputs are always uncontrolled components because its value can only be set by a user and not programmatically.

Therefore, we have to use a ref to access its value.

For example, we can write the following:

class App extends React.Component {  
  constructor(props) {  
    super(props);  
    this.fileRef = React.createRef();  
  } 

  handleSubmit(event) {  
    alert(`Filename: ${this.fileRef.current.files[0].name}`);  
    event.preventDefault();  
  } 

  render() {  
    return (  
      <form onSubmit={this.handleSubmit.bind(this)}>  
        <input type="file" ref={this.fileRef} />  
        <input type="submit" value="Submit" />  
      </form>  
    );  
  }  
}

In the code above, we created a ref called fileRef and attached it to the file input. Then we get the files[0].name property that has the name of the selected file.

We can use the File API to do things with the selected file.

Conclusion

We can use uncontrolled components to get input values directly from the DOM.

This is useful for integrating React and non-React code. It’s also useful for quick and dirty apps.

We can set the default value of an uncontrolled input by setting the defaultValue attribute with a value.

Also, file inputs are always uncontrolled. We use the File API to manipulate selected files from file inputs.