Categories
React Tips

React Tips — Input Focus and Choices Controls

React is the most used front end library for building modern, interactive front end web apps. It can also be used to build mobile apps.

In this article, we’ll look at how to focus inputs and binding values of checkboxes and radio buttons to states.

Set Focus On Input After Render

To focus an input, we have to use the native DOM element focus method to do it. The method is available to input elements so we can call it.

We can use the useEffect hook to run something when the component renders. If we pass in an empty array as the 2nd argument, then the callback we pass into useEffect only runs when the component first loads.

For instance, we can write the following to do that:

import React from "react";

export default function App() {
  const input = React.createRef();
  React.useEffect(() => input.current.focus(), []);
  return (
    <div className="App">
      <input ref={input} />
    </div>
  );
}

In the code above, we have the useEffect hook and the input ref created with the createRef method, which passed into the ref prop of the input.

Then in the useEffect callback, we call input.current.focus() to call the focus method of our input element.

In the end, when we load the page, we’ll see that the input is focused when App loads as we desired.

Checkbox

To create checkboxes, we have to set the checkbox value as the value of the checked prop. Then onChange handler will take the checked value and then set it to the state we passed in as the value of the checked prop.

For instance, we can write the following to do that:

import React from "react";

export default function App() {
  const [selected, setSelected] = React.useState({});
  const handleInputChange = e => {
    const { name, checked } = e.target;
    setSelected(selected => ({
      ...selected,
      [name]: checked
    }));
  };
  return (
    <div className="App">
      <form>
        <label>
          apple:
          <input
            name="apple"
            type="checkbox"
            checked={selected.apple || false}
            onChange={handleInputChange}
          />
        </label>
        <label>
          orange:
          <input
            name="orange"
            type="checkbox"
            checked={selected.orange || false}
            onChange={handleInputChange}
          />
        </label>
        <label>
          grape:
          <input
            name="grape"
            type="checkbox"
            checked={selected.grape || false}
            onChange={handleInputChange}
          />
        </label>
      </form>
      <p>
        {Object.keys(selected)
          .filter(k => selected[k])
          .join(", ")}
      </p>
    </div>
  );
}

Making checkboxes work properly is tricky. In our handleInputChange function, we have to make sure that name and value properties of e.target have to be accessed from a synchronous context, so it can’t be inside the callback that we pass into setSelected . If we don’t do that, we get a warning saying that ‘ This synthetic event is reused for performance reasons happening’

In the setSelected function, we spread the existing properties of selected , and then update the name and checked values from e.target into the returned object in the setSelected callback.

The name value is from the value of the name attribute of each checkbox.

To get rid of the ‘A component is changing an uncontrolled input of type text to be controlled error in ReactJS’ error, we have to set a default value for each checked prop. In the code above, we set them to false .

Radio Buttons

Radio buttons are similar to checkboxes, but only one radio button in a group can be checked at one time. For instance, we can write the following code to bind the radio button’s checked value to a state as follows:

import React from "react";

export default function App() {
  const [selected, setSelected] = React.useState("");
  const handleInputChange = e => {
    setSelected(e.target.value);
  };
  return (
    <div className="App">
      <form>
        <label>
          apple:
          <input
            name="fruit"
            type="radio"
            value="apple"
            checked={selected === "apple"}
            onChange={handleInputChange}
          />
        </label>
        <label>
          orange:
          <input
            name="fruit"
            type="radio"
            value="orange"
            checked={selected === "orange"}
            onChange={handleInputChange}
          />
        </label>
        <label>
          grape:
          <input
            name="fruit"
            type="radio"
            value="grape"
            checked={selected === "grape"}
            onChange={handleInputChange}
          />
        </label>
      </form>
      <p>{selected}</p>
    </div>
  );
}

In the code above, we have the checked prop which is set to the expression that checks if the selected value is set to given value in the value prop.

Then in the handleInputChange function, we can call setSelected by writing setSelected(e.target.value) since the radio button sets e.target.value is set to the value of the radio button.

Therefore, the selected value will be displayed when we click the radio button, and we also see the radio buttons change the selection as soon as we click the radio button.

The checked prop controls the rendering of which radio button is selected and the value displayed in the p tag is updated with the handleInputChange function.

Conclusion

Setting the values of checkboxes is tricky in React. We’ll get warnings in the console if we didn’t set a default value in the checked prop of the checkbox. We’ll also get warnings if we access e.target within the callback of our state change functions.

Radio buttons are easier to deal with in React since we just set the value as a string when we click a radio button.

Focusing inputs is easy since we can just attach a ref to an input and then call focus on it.

Categories
React Tips

React Tips — Input Data Binding

React is the most used front end library for building modern, interactive front end web apps. It can also be used to build mobile apps.

In this article, we’ll look at how to add various form controls to our React app and set the state to the value of the control.

Drop-Downs

Dropdowns is a common form input control element added to many apps. It’s the select element in HTML. In React, we have to set the value attribute of the select element to the value we selected in addition to adding the onChange handler to add a handler to get the selected value and set it as the state.

For instance, we write the following code to do that:

import React from "react";

export default function App() {
  const [fruit, setFruit] = React.useState("");
  return (
    <div className="App">
      <select value={fruit} onChange={e => setFruit(e.target.value)}>
        <option value="apple">apple</option>
        <option value="orange">orange</option>
        <option value="grape">grape</option>
      </select>
      <p>{fruit}</p>
    </div>
  );
}

In the code above, we have the select element, which has various options. The value prop is set to the fruit state, and we have a function that calls setFruit to update the value of fruit .

Then we have the value of fruit rendered inside the p element. The onChange handler will update fruit so that the selected value is displayed when we change the drop-down choice.

We can omit the value attribute’s value if the drop-down text and value are the same.

Multiple Select Values

A select element can also be used to select multiple values. Instead of a drop-down, it’ll be a box where we can press Ctrl-click to select multiple values.

We can get the multiple selected values and then set them to a state by retrieving the values with the selected property set to true .

For instance, we can write the following to do that:

import React from "react";

export default function App() {
  const [fruits, setFruits] = React.useState("");
  const handleChange = e => {
    const options = e.target.options;
    setFruits(
      [...options]
        .filter(o => o.selected)
        .map(o => o.value)
        .join(",")
    );
  };
  return (
    <div className="App">
      <select multiple onChange={handleChange}>
        <option>apple</option>
        <option>orange</option>
        <option>grape</option>
      </select>
      <p>{fruits}</p>
    </div>
  );
}

In the code above, we set the multiple prop of select to true to enable multiple-choice selections in our select element.

Then in our handleChange function, we spread the options array-like object, which has all the choices.

Next, we keep the ones that are selected in a new array by calling filter with a callback that returns the ones with selected set to true . Then we map those into an arrays by passing in a callback which returns the value property.

Then we call join to join the array of strings into one string.

Therefore, when we select one or more items from the multiple select box, we get the selected choices displayed separated by a comma.

Text Input

Like with the single select drop-down, we have to set the value prop to the state that holds the entered value and the onChange handler to the function which gets the inputted value and then set them to the state which is passed into the value prop.

For instance, we can write that as follows:

import React from "react";

export default function App() {
  const [fruit, setFruit] = React.useState("");
  return (
    <div className="App">
      <label>Favorite Fruit</label>
      <br />
      <input value={fruit} onChange={e => setFruit(e.target.value)} />
      <p>{fruit}</p>
    </div>
  );
}

In the code above, we have the input element. We pass in the fruit state to value . Therefore to update it with the inputted text, we have to call setFruit with e.target.value , which has the inputted value to update the fruit state.

The fruit state is then rendered in the p element. In the end, when we enter something in the text input, we’ll see the entered text displayed in the p element.

Conclusion

We can add select elements and bind the selected value to a state variable with the onChange handler. Then we set the value prop with the state that we updated.

To add a select box that let users choose multiple options, we can add a select element and set the multiple prop to true . Then in the onChange handler, we get the options with the e.target.options array-like object. To use array options on it, we convert it to an array by using the spread operator.

Then we can select the selected properties by keeping the ones with selected property set to true .

Binding the inputted value of the text input to a state is done similarly to the way that we bind to select elements. We have an onChange handler, which calls the state change function returned from useState to update the state with the inputted value.

Categories
React Tips

React Tips — Component Organization and Web Components

React is the most used front end library for building modern, interactive front end web apps. It can also be used to build mobile apps. In this article, we’ll look at some tips and tricks to make building apps with React easier.

Keeping Components Small

Keeping components small making them easy to read, change, and test. They’re also easier to debug and maintain. It’s more than 30 lines of code, it’s probably too big.

We can easily split up components into smaller ones by passing props between them if they’re parent and child.

If they aren’t related, we can also use a state management solution like Redux or the context API.

They do less and so they’re more likely to be reused since they fit more use cases.

For example, the following is a small component:

import React from "react";

export default function App() {
  const [count, setCount] = React.useState(0);
  return (
    <div className="App">
      <button onClick={() => setCount(count + 1)}>Increment</button>
      <p>{count}</p>
    </div>
  );
}

It’s short and it doesn’t do much on its own.

Avoid Components That are Too Small

Components that are too small are also a problem. We don’t want lots of components that are one or 2 lines. Also, we don’t want every div, span, or paragraph to be its own component.

We should make them reusable by letting them accept props. For instance, we shouldn’t have components that are like this everywhere in our app:

const Foo = <p>foo</p>;

Using Web Components in React

We can put web components straight into React components and use them.

For instance, we can define a web component and then use it as follows:

import React from "react";

class FooParagraph extends HTMLElement {
  constructor() {
    super();
  }

  connectedCallback() {
    const shadow = this.attachShadow({ mode: "open" });
    const p = document.createElement("p");
    p.setAttribute("class", "wrapper");
    p.textContent = this.getAttribute("text");
    shadow.appendChild(p);
  }
}

customElements.define("foo-paragraph", FooParagraph);

export default function App() {
  return (
    <div className="App">
      <foo-paragraph text="abc" />
    </div>
  );
}

In the code above, we have the FooParagraph web component class. Inside the class, we have the connectedCallback , which gets the attribute value for text and then add a p tag with the text ‘s value into the shadow DOM.

Then we call customElements.define to define a new web component. And then we put it straight into the App React component.

Using React in Our Web Components

We can also create web components with React by mounting our React component inside a web component as follows:

src/index.js :

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

class XParagraph extends HTMLElement {
  connectedCallback() {
    const mountPoint = document.createElement("div");
    this.attachShadow({ mode: "open" }).appendChild(mountPoint);

    const text = this.getAttribute("text");
    ReactDOM.render(<p>{text}</p>, mountPoint);
  }
}
customElements.define("x-paragraph", XParagraph);

index.html :

<!DOCTYPE html>
<html>
  <head>
    <title>App</title>
    <meta charset="UTF-8" />
  </head>

  <body>
    <div id="app"></div>
    <x-paragraph text="foo"></x-paragraph>
    <script src="src/index.js"></script>
  </body>
</html>

The code above are parts of a project that’s created with Parcel. Therefore, we can use modules in a script.

We have a XParagraph web component that has the ReactDOM.render call to render a p React element with the text attribute’s value taken from the attribute of the web component.

Then we defined the web component with customElements.define with the name of the element as the first argument, and the HTMLElement class as the second argument.

In index.html , we added the x-paragraph web component with the text attribute set to foo , so that we display the text content inside the element by calling this.getAttribute('text') and then passing in the returned value to ReactDOM.render .

Therefore, we see the word ‘foo’ on the screen.

Conclusion

To make development, testing, and reading the code easy, we should keep components small. Around 30 lines or less is a good size.

However, they shouldn’t be too small, like 1 or 2 lines, since we would have to manage too many of them. That’s even worse if they don’t take any props. To make sure that they’re reusable, we should make sure that they take props if they share any data.

React components can be embedded into web components to create easily reusable web components with React.

Also, we can embed web components in a React component so that we can take advantage of standards-compliant custom HTML elements that we can use anywhere.

Categories
React Tips

React Tips and Tricks — Fragments and Error Handling

React is the most used front end library for building modern, interactive front end web apps. It can also be used to build mobile apps. In this article, we’ll look at some tips and tricks to make building apps with React easier.

React Fragments

We can’t have multiple root nodes in a React component. However, we can have a single root node that doesn’t render any component by using a React fragment as the root node.

We can reference a React fragment with the React.Fragement component or an empty tag.

For instance, we can write the following:

import React from "react";
`
export default function App() {
  return (
    <React.Fragment>
      <p>foo</p>
      <p>bar</p>
    </React.Fragment>
  );
}

or:

import React from "react";
`
export default function App() {
  return (
    <>
      <p>foo</p>
      <p>bar</p>
    </>
  );
}

<React.Fragment> is the same as <> .

Use Error Boundaries to Handle Errors Gracefully

Error boundaries are components that are displayed when there’re errors. They have special hooks like componentDidCatch to let us retrieve error details and does actions on error accordingly.

We wrap error boundary components around components that may throw errors for them to work.

Error boundary components are always class-based components. There’s no function component equivalent for this.

For instance, we can define an error boundary component and use it as follows:

import React from "react";
`
function Foo() {
  throw new Error("error");
  return <div>foo</div>;
}
`
class ErrorBoundary extends React.Component {
  constructor(props) {
    super(props);
    this.state = { hasError: false };
  }
  componentDidCatch(error, info) {
    this.setState({ hasError: true });
  }
  render() {
    if (this.state.hasError) {
      return <h1>Error occurred.</h1>;
    }
    return this.props.children;
  }
}
`
export default function App() {
  return (
    <ErrorBoundary>
      <Foo />
    </ErrorBoundary>
  );
}

In the code above, we defined the ErrorBoundary component, which has the componentDidCatch hook, which takes the error parameter with the error that’s raised, and info object with the error information.

Then we call setState to hasError to true so that we render an error message. We return this.props.children when there’re no errors so that we display the components that we put inside the ErrorBoundary component.

Therefore, when we have Foo , where we threw an error, then we display the ‘Error occurred’ message since Foo throws an error before rendering anything.

Higher-Order Components

Higher-order components are components that render other components. It’s useful because it can be used to produce components that are modified by the higher-order component.

For instance, we can create a colorizeElement higher-order component to apply the color prop to a component with the value blue as the default. If the color prop is set, then it’ll override the value of the color prop that we pass inside.

We can create and use it as follows:

import React from "react";
`
const colorizeElement = Element => props => <Element color="blue" {...props} />;
`
const Foo = ({ color }) => {
  return <p style={{ color }}>foo</p>;
};
`
const ColoredFoo = colorizeElement(Foo);
`
export default function App() {
  return (
    <>
      <ColoredFoo color="red" />
      <ColoredFoo />
    </>
  );
}

In the code above, we have the ColoredFoo component that we created from the colorizeElement higher-order component. In the component, we pass in the Element , which is a React component, which returns a new function with props as a parameter and returns the Element with the color prop set as 'blue' and also pass in other props that are passed in.

Then in App , we have the ColoredFoo components, one with color prop set and the other one without. Then the first one is red and the second is blue.

React DevTools

React dev tools is an extension for Chrome and Firefox and it’s maintained by the React core team. It lets us inspect the values of props and states that are inside components.

We’ll run into bugs and issues that are hard to solve eventually, so it’s a handy tool for debugging.

Conclusion

Error boundaries and higher-order components are great for displaying errors and modifying components respectively.

Fragments are great for rendering multiple items within one single root node. It doesn’t render any HTML element itself.

React dev tools is a great extension for debugging.

Categories
React Tips

React Tips — Async and setState

React is the most used front end library for building modern, interactive front end web apps. It can also be used to build mobile apps.

In this article, we’ll look at the async nature of setState and how we should write our code to run multiple setState calls sequentially.

setState’s Asynchronous Nature

The setState method is the method to update the component’s internal state. It’s an asynchronous method that’s batched. This means that multiple setState calls are batched before a component is rerendered with the new state.

setState doesn’t immediately mutate the state but creates a pending state transaction. This means that accessing the state immediately after call setState can possibly return the old value.

The setState method takes up to 2 arguments. We usually pass in only one. The first argument can be an object or a callback that’s used to update the state.

The second argument is a function that’s always run after setState is run. For instance, we can pass in a callback in the 2nd argument as follows:

import React from "react";
`
class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = { count: 0 };
  }
`
  update() {
    this.setState(
      ({ count }) => ({
        count: count + 1
      }),
      () => {
        this.setState(({ count }) => ({
          count: count + 2
        }));
      }
    );
  }
`
  render() {
    return (
      <>
        <button onClick={this.update.bind(this)}>Increment</button>
        <p>{this.state.count}</p>
      </>
    );
  }
}
`
export default App;

In the code above, we have:

update() {
  this.setState(
    ({ count }) => ({
      count: count + 1
    }),
    () => {
      this.setState(({ count }) => ({
        count: count + 2
      }));
    }
  );
}

which calls setState once, and then calls setState again in the callback. This will ensure that one will run after the other.

Therefore, when we click the Increment, the count state will increase by 3 every time.

setState Takes an Object or Function

As we can see from the code above, setState can take a callback that returns the new state based on the previous state. This is useful for updating states that are based on the previous state.

In the code above, the new count is based on the old count , so passing in a callback is more appropriate than passing in an object since we can guarantee that the original state is the lastest when it’s passed in as the callback parameter.

It also takes a props parameter as the second parameter which has the props. For instance, we can use it as follows:

import React from "react";
`
class Counter extends React.Component {
  constructor(props) {
    super(props);
    this.state = { count: 0 };
  }
`
  update() {
    this.setState(({ count }, { incrementVal }) => ({
      count: incrementVal + count
    }));
  }
`
  render() {
    return (
      <>
        <button onClick={this.update.bind(this)}>Increment</button>
        <p>{this.state.count}</p>
      </>
    );
  }
}
`
export default function App() {
  return <Counter incrementVal={5} />;
}

In the code above, we have the Counter component, which has the update method as we have in the previous example. But this ti,e, the setState method takes a callback which has a second parameter. It has the props object.

We can get the prop property values as we did above via the destructuring assignment syntax. Also, we can access the prop object’s property like any other JavaScript object property with the dot or bracket notation.

Therefore, since we have:

<Counter incrementVal={5} />

in App , when we click the Increment button, the count state in Counter will update by 5 since that’s what we specified.

The most common entity that we pass into setState is probably an object. We just pass in an object that has state properties that we want to change. The ones that aren’t included will stay the same.

For instance, if we write:

import React from "react";
`
class Counter extends React.Component {
  constructor(props) {
    super(props);
    this.state = { count: 0, foo: "foo" };
  }
`
  update() {
    this.setState({ count: this.state.count + 1 });
  }
`
  render() {
    return (
      <>
        <button onClick={this.update.bind(this)}>Increment</button>
        <p>{this.state.count}</p>
        <p>{this.state.foo}</p>
      </>
    );
  }
}
`
export default function App() {
  return <Counter />;
}

Then this.state.foo has the value 'foo' even after this.setstate in update is run.

Therefore, when we click the Increment button, we see ‘foo’ displayed no matter how many times we click it.

Conclusion

setState calls may not be always sequential. The batching sometimes may not be controlled by React. Therefore, if we want to make sure that multiple setState calls run sequentially all the time, we should run the second setState in the callback that’s passed in as the 2nd argument of setState .

Also, setState can take an object or a function with the previous state and the props objects as the 1st and 2nd parameters respectively.