Categories
React Tips

React Tips — Form Validation

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 do form validation in React apps.

Form Validation and React

Form validation isn’t included in React since it’s just a view library. We’ve to deal with watching form values and form validation ourselves. To make the job easy, we can use a library to do it.

React Hook Form

One easy library that we can use to do form validation is the React Hook Form library.

We can get started by running the following to install it:

npm install react-hook-form

Once we install it, we can use it as follows:

import React from "react";
import { useForm } from "react-hook-form";

export default function App() {
  const { register, handleSubmit, watch, errors } = useForm();
  const onSubmit = data => {
    console.log(data);
  };

  console.log(watch("name"));

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <input
        name="name"
        defaultValue="foo"
        ref={register({ required: true })}
      />
      {errors.name && <span>This field is required</span>}
      <input name="age" ref={register} />
      <input type="submit" />
    </form>
  );
}

In the code above, we used the react-hook-form library to create a form first by using the useForm hook that’s built into react-hook-form to return a few objects that we need to create a form with validation.

Then we create a form with validation by passing in the handleSubmit function into the onSubmit function, which is our submit handler, as the argument.

Then we set the name of the input, which is used for form validation. In the ref prop, we pass in the register function, with the required property set as an optional property to indicate that it’s a required field.

The defaultValue prop lets us set the default value of an input.

If it’s not a field that needs validation, then we just pass in the reference of the register function that’s returned from the useForm hook.

To display error messages, we can get the errors.name variable to get any errors from a field with the given name. In this case, errors.name get the errors from the field with the name attribute set to name .

Then if that’s true , we display an error message.

We can also watch values with the watch function as we have above.

Notice that it doesn’t have any form value handling code. It’s all done by react-hook-form , which is good since it’s less typing for us.

In the end, when we type in something into the input, we’ll see it displayed in the box. When we don’t have anything in the required name input and click Submit, we’ll get an error.

Validation Rules

We can easily change the basic form we have above to include validation rules like number range.

For instance, we can add a number range validation into the age input in the example above as follows:

import React from "react";
import { useForm } from "react-hook-form";

export default function App() {
  const { register, handleSubmit, watch, errors } = useForm();
  const onSubmit = data => {
    console.log(data);
  };

  console.log(watch("name"));

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <input
        name="name"
        defaultValue="foo"
        ref={register({ required: true })}
      />
      {errors.name && <span>This field is required</span>}
      <input
        name="age"
        type="number"
        ref={register({ required: true, min: 0, max: 200 })}
      />
      {errors.age && <span>Age must be between 0 and 200</span>}
      <input type="submit" />
    </form>
  );
}

In the code above, we changed the age input to:

<input
  name="age"
  type="number"
  ref={register({ required: true, min: 0, max: 200 })}
/>

We added the min and max validators and set the input type to number. This way, we get validation of numeric ranges.

Then we added an error display below it which displays when error.age is true .

Conclusion

We can do basic form validation with the react-hook-form package. It lets us easily create forms by using the useForm hook and passing in a few props.

It also handles data binding and form submission without writing our own code to do it.

The package comes with its own validation rules, which can be applied flexibly. We can also watch the values of each field as it changes.

Categories
React Tips

React Tips — Stateless Components and Spreading Props

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 use stateless components to simplify our code and spreading props so we don’t have to pass them explicitly.

Stateless Components

Stateless components are components that don’t hold state. We can define stateless components with function and class components.

They only take props and render them.

They’re easy to test since we don’t have to mock and change states in order to test them.

We can define the class component that is stateless as follows:

import React from "react";

class Person extends React.Component {
  render() {
    const { firstName, lastName, age } = this.props;
    return (
      <p>
        {firstName} {lastName} {age}
      </p>
    );
  }
}

In the code above, we have the render method that render firstName , lastName , and age from the props by destructuring this.props .

Then when we add the following below Person:

export default function App() {
  return (
    <>
      <div>
        <Person firstName="Jane" lastName="Smith" age={20} />
      </div>
    </>
  );
}

We’ll see Jane Smith 20 displayed on the screen.

We can make stateless components a lot simpler with function components. For instance, we can rewrite Person as a function component as follows:

import React from "react";

const Person = ({ firstName, lastName, age }) => {
  return (
    <p>
      {firstName} {lastName} {age}
    </p>
  );
};

In the code above, we have a React function component. The first parameter has our props. We destructured the prop’s properties into individual variables.

Then we return them in immediately in the p element.

This is a lot simpler and we also saved a lot of typing by eliminating lots of boilerplate code that class-based components need to have.

Spreading Props as we Pass Them

To make passing lots of props cleaner, we can use the spread operator to spread them so that we don’t have to pass props by writing them all out explicitly.

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

import React from "react";

const person = {
  firstName: "Jane",
  lastName: "Smith",
  age: 20
};

const Person = ({ firstName, lastName, age }) => {
  return (
    <p>
      {firstName} {lastName} {age}
    </p>
  );
};

export default function App() {
  return (
    <>
      <div>
        <Person {...person} />
      </div>
    </>
  );
}

In the code above, we have the person object. We want to pass in the properties of person as props. In the code above, we passed in the firstName , lastName and age prop by spreading the person object as follows:

<Person {...person} />

Then the Person prop, will pick up the values of firstName , lastName , and age and render them in the p element of Person .

This is much cleaner than writing them out one by one as follows:

import React from "react";

const person = {
  firstName: "Jane",
  lastName: "Smith",
  age: 20
};

const Person = ({ firstName, lastName, age }) => {
  return (
    <p>
      {firstName} {lastName} {age}
    </p>
  );
};

export default function App() {
  return (
    <>
      <div>
        <Person
          firstName={person.firstName}
          lastName={person.lastName}
          age={person.age}
        />
      </div>
    </>
  );
}

As we can see:

<Person
  firstName={person.firstName}
  lastName={person.lastName}
  age={person.age}
/>

is a lot longer than:

<Person {...person} />

In the shorter version, we didn’t have to reference person and the prop names in every line. It’s way shorter and saved us lots of typing, and they do the same thing.

Deduplicate Our Components

If we have code that’s very similar to each other, we should find a way to deduplicate them. For instance, the following code has lots of duplicate code:

import React from "react";

const Person = ({ firstName, lastName, age }) => {
  return (
    <p>
      {firstName} {lastName} {age}
    </p>
  );
};

export default function App() {
  return (
    <>
      <div>
        <Person firstName="John" lastName="Smith" age={20} />
        <Person firstName="Jane" lastName="Smith" age={20} />
      </div>
    </>
  );
}

In the code above, we have:

<Person firstName="John" lastName="Smith" age={20} />
<Person firstName="Jane" lastName="Smith" age={20} />

which is mostly overlapping code except for the value of the firstName prop.

We can clean that up by creating another component that has shared parts in one place. For example, we can write the following code to do that:

import React from "react";

const common = {
  firstName: "Jane",
  lastName: "Smith",
  age: 20
};

const Person = ({ firstName, lastName, age }) => {
  return (
    <p>
      {firstName} {lastName} {age}
    </p>
  );
};

const FamilyMember = ({ firstName }) => {
  return <Person {...common} firstName={firstName} />;
};

export default function App() {
  return (
    <>
      <div>
        <FamilyMember firstName="John" />
        <FamilyMember firstName="Jane" />
      </div>
    </>
  );
}

In the code above, we have the FamilyMember component, which has the common object’s properties set as props to eliminate the duplicate prop values, then we reference FamilyMember in App , which only has common props in one place.

Then we get:

John Smith 20

Jane Smith 20

displayed on the screen. Putting the code in one makes changing it easier even though it may not be the shortest way in this case.

Conclusion

We should use stateless components wherever we can to reduce the burden of testing. They’re also simpler.

Also, we can spread props into components so that we don’t have to write them all out.

Finally, if we have components with lots of common props, we should eliminate the duplicates by putting them all in one component.

Categories
React Tips

React Tips — Loading Data

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 load data in our React components.

Loading Data When the Component First Loads with the useEffect Hook

If we’re using hooks in React function components, we can load data from an API when the component first loads by using the useEffect hook with an empty array as the second argument.

For instance, we can load data by writing:

import React, { useEffect, useState } from "react";

export default function App() {
  const [data, setData] = useState({});
  const loadData = async () => {
    const res = await fetch("https://api.agify.io/?name=michael");
    setData(await res.json());
  };

  useEffect(() => {
    loadData();
    return () => {};
  }, []);
  return <p>{data.name}</p>;
}

In the code above, we use the useEffect hook to fetch data from an API and then set the result to the data state variable with the setData function.

Then we call the loadData function in the useEffect callback. The 2nd argument of the useEffect hook is an empty array.

React then will rerender the data as the data from the API is fetched. The useEffect callback will only run when the component first loads if the 2nd argument of useEffect is an empty array.

Loading Data When the Component’s Prop Changes

If we pass in the prop variable to the array in the 2nd argument of useEffect , the callback that we pass into the 1st argument will run as the prop changes.

For instance, we can write the following code fetch data from an API as our prop changes:

import React, { useEffect, useState } from "react";

const Name = ({ name }) => {
  const [data, setData] = useState({});
  const loadData = async () => {
    const res = await fetch(`https://api.agify.io/?name=${name}`);
    setData(await res.json());
  };

  useEffect(() => {
    loadData();
    return () => {};
  }, [name]);
  return <p>{data.name}</p>;
};

export default function App() {
  const [name, setName] = useState("");
  return (
    <div>
      <input onChange={e => setName(e.target.value)} />
      <Name name={name} />
    </div>
  );
}

In the code above, we have an input in App , where the inputted value is set as the value of the name variable with setName . Then we have the Name component, which passes the name prop with the value name ,

In Name , we have the useEffect hook which is similar to what we have before. The name prop is passed into the array in the second argument of useEffect , which means that it’s watched.

Note that we returned a function in the useEffect callback. This is used for clean up code. Whenever we have something in the array in the 2nd argument of useEffect , we have to return a cleanup function. Otherwise, we’ll get a ‘destroy is not a function’ error.

Then when we type in something, we’ll see that data is fetched from the API and the data is displayed as the output.

Adding a Loading Indicator in Fetch Calls

We can use the react-promise-tracker package to watch for loading promises and sets a state to indicate that one or more promises are loading.

To use it, we first install it by running:

npm i react-promise-tracker

Then we can use it as follows:

import React, { useEffect, useState } from "react";
import { usePromiseTracker, trackPromise } from "react-promise-tracker";

const sleep = ms => new Promise(r => setTimeout(r, ms));

export default function App() {
  const [data, setData] = useState({});
  const { promiseInProgress } = usePromiseTracker();
  const loadData = async () => {
    await sleep(2000);
    const res = await fetch("https://api.agify.io/?name=michael");
    setData(await res.json());
  };
  useEffect(() => {
    trackPromise(loadData());
    return () => {};
  }, []);

  return <p>{promiseInProgress ? "loading" : data.name}</p>;
}

In the code above, we have 2 promises. One if the sleep function call, which returns a promise. Then we have our fetch request promises in the loadData function.

We then use the trackPromise function from react-promise-tracker to track whether the promises are finished or not.

If one or more promises are loading, then we have the promiseInProgress state is set to true . When it’s true , we show the ‘loading’ text. When the promises are done, we show the value of data.name .

This is a great package that makes tracking the loading of promises easy. We can also add a delay as follows to delay the loading of the promise as follows:

import React, { useEffect, useState } from "react";
import { usePromiseTracker, trackPromise } from "react-promise-tracker";

const sleep = ms => new Promise(r => setTimeout(r, ms));

export default function App() {
  const [data, setData] = useState({});
  const { promiseInProgress } = usePromiseTracker({ delay: 500 });
  const loadData = async () => {
    await sleep(2000);
    const res = await fetch("https://api.agify.io/?name=michael");
    setData(await res.json());
  };
  useEffect(() => {
    trackPromise(loadData());
    return () => {};
  }, []);

  return <p>{promiseInProgress ? "loading" : data.name}</p>;
}

In the code above, we have:

usePromiseTracker({ delay: 500 })

to prevent flickering when the component is loaded on high-speed connections.

Conclusion

In React function components, it isn’t immediately obvious where we place our code to load data. The correct way is to add callbacks to the useEffect hook.

The 2nd argument of useEffect will indicate when the callback will run. If it’s empty, then it’s run when the component first loads. If it’s not, then it’ll watch the value changes of the items in the array and runs the callback when any of them change.

We have to return a cleanup function to run clean up code if needed. Even if we don’t, we still need to return an empty function.

To add a loading indicator when promises load, we can use the react-promise-tracker package to track that and render the loading indicator according to the state returned by this package.

Categories
React Tips

React Tips — Conditionals

React is one of the most popular libraries for creating front end apps. It can also be used to create mobile apps with React Native.

In this article, we’ll look at how to display items conditionally in various ways.

Conditionally Displaying Items

There’re a few ways to display items conditionally with React. We can use conditional statements like if and switch statements. If we’re only toggling between 2 items, then we can also use ternary expressions.

To use ternary expressions, we can write the following code to do that:

import React from "react";

export default function App() {
  const [on, setOn] = React.useState(true);
  return (
    <div className="App">
      <button onClick={() => setOn(on => !on)}>toggle</button>
      {on ? <p>on</p> : <p>off</p>}
    </div>
  );
}

In the code above, we have a toggle button, which when clicked, toggles the on state between true and false .

If on is true , we render ‘on’. Otherwise, we render ‘off’. The following is the ternary expression that we used to do that:

{on ? <p>on</p> : <p>off</p>}

This is great because we don’t have to write if statements to do the same thing, which is much longer.

It’s also an expression, which means that we can embed it in our React code without creating a function unlike if or switch statements.

Therefore, this is much better than using conditional statements if we only display one thing or another based on some condition.

We can write this in an even shorter way if we don’t display anything if on is false .

In this case, we can just use the && operator because it evaluates both operands to see if they both are truthy. If the first operand is falsy, then it’ll just return false instead of evaluating the 2nd operand.

For instance, we can use it as follows:

import React from "react";

export default function App() {
  const [on, setOn] = React.useState(true);
  return (
    <div className="App">
      <button onClick={() => setOn(on => !on)}>toggle</button>
      {on && <p>on</p>}
    </div>
  );
}

In the code above, if on is true then it’ll evaluate the 2nd operand, which is <p>on</p> . Otherwise, it’ll just return false .

Therefore, when on is true , then <p>on</p> will be rendered.

If we have anything longer, then we need to write out the full conditional statement. We should do that in its own function or component.

For instance, if we display more things based on more cases than 2, then we need to write them out as we do in the following code:

import React from "react";

const Fruit = ({ val }) => {
  if (val === 0) {
    return <p>apple</p>;
  } else if (val === 1) {
    return <p>orange</p>;
  } else if (val === 2) {
    return <p>grape</p>;
  }
};

export default function App() {
  const [num, setNum] = React.useState(0);
  return (
    <div className="App">
      <button onClick={() => setNum(num => (num + 1) % 3)}>rotate</button>
      <Fruit val={num} />
    </div>
  );
}

In the code above, we have the Fruit component, which is a stateless component that returns the name of a fruit and displays it in a p element, based on the value of the val prop that’s passed in.

Then in our App component, we have the button, which rotates between the numbers by calling setNum to update the number by rotating them between 0, 1 and 2.

Therefore, when we click the rotate button, we get that we’ll see the name of the fruit rotate between ‘apple’, ‘orange’ and ‘grape’.

Likewise, we can do the same with the switch statement as follows:

import React from "react";

const Fruit = ({ val }) => {
  switch (val) {
    case 0: {
      return <p>apple</p>;
    }
    case 1: {
      return <p>orange</p>;
    }
    case 2: {
      return <p>grape</p>;
    }
    default: {
      return undefined;
    }
  }
};

export default function App() {
  const [num, setNum] = React.useState(0);
  return (
    <div className="App">
      <button onClick={() => setNum(num => (num + 1) % 3)}>rotate</button>
      <Fruit val={num} />
    </div>
  );
}

The code above is longer since we should put a default case no matter if it’s used or not just in case when we run into some unexpected value.

Also, we used case blocks instead of case statements so that we can define block-scoped variables with the same name in each block if needed, so it’s good practice to use it any time.

In the end, we get the same result as before.

If we have if and switch statements in our component, then it’s better to put them inside their own component since they’re long.

Conclusion

There’re many ways to display things conditionally in React components. We can use ternary expressions if we have 2 cases. If we want to display one thing conditionally, we can use the && operator.

Otherwise, we should put if and switch statements in their own component if we need them.

Categories
React Tips

React Tips — Rendering Lists, Dynamic Components, and Default Props

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 render lists in React components, rendering components dynamically, and setting default props.

Rendering Lists

We can render lists by mapping our data to the component that we use to render the list item.

To do the mapping, we use the array’s map instance method. We can do that as follows:

import React from "react";

const persons = [
  { firstName: "Jane", lastName: "Smith" },
  { firstName: "Alex", lastName: "Jones" },
  { firstName: "May", lastName: "Wong" }
];

const Person = ({ firstName, lastName }) => (
  <div>
    {firstName} {lastName}
  </div>
);

export default function App() {
  return (
    <div>
      {persons.map((p, i) => (
        <Person {...p} key={i} />
      ))}
    </div>
  );
}

In the code above, we have the Persons array, which we call map on in App . In the map method, we pass in a callback to return the Person component with all the properties of each persons entry passed in as props.

We need the key prop so that React can identify them properly. Ideally, it’s a unique ID, but the array index can also be the value of the key prop.

Then in Person , we have the props in the parameters and we decompose the prop properties in variables with the destructuring syntax.

Therefore <Person {...p} /> is the same as:

<Person firstName={p.firstName} lastName={p.lastName} key={i} />

It’s a lot shorter if our prop name is the same as our object’s property names.

In the end, we see:

Jane Smith
Alex Jones
May Wong

displayed on the screen.

Dynamic Component Names

React components can have dynamic components. As long as the variable name starts with an upper case, it can be used as a dynamic component. We can render components with dynamic component names as follows:

import React from "react";

const Foo = ({ text }) => <p>{text} foo</p>;
const Bar = ({ text }) => <p>{text} bar</p>;

const components = {
  foo: Foo,
  bar: Bar
};

export default function App() {
  const [name, setName] = React.useState("foo");
  const toggle = () => {
    setName(name => (name === "foo" ? "bar" : "foo"));
  };

  const Component = components[name];
  return (
    <>
      <div>
        <button onClick={toggle}>Toggle</button>
        <Component text="hello" />
      </div>
    </>
  );
}

In the code above, we have the name state, which is set by the setName function. The toggle function calls setName to change the name.

Outside the toggle function in App , we set the Component variable by using:

const Component = components[name];

Then we return the Component to render it. We can pass props to it like any other static component.

Therefore, when we click the toggle button, we should see ‘hello foo’ and ‘hello bar’ displayed as the button is clicked.

Default Props

We can add default props to make sure we always have some values set for our props.

To set default props, we use the defaultProps property to set the default values of each prop;

For instance, we can write the following code to set default props for the Person component that we have above:

import React from "react";
const persons = [
  { firstName: "Jane", lastName: "Smith" },
  { firstName: "Alex", lastName: "Jones" },
  { firstName: "May", lastName: "Wong" },
  {}
];
const Person = ({ firstName, lastName }) => (
  <div>
    {firstName} {lastName}
  </div>
);
Person.defaultProps = {
  firstName: "No",
  lastName: "Name"
};

export default function App() {
  return (
    <div>
      {persons.map((p, i) => (
        <Person {...p} key={i} />
      ))}
    </div>
  );
}

In the code above, we added:

Person.defaultProps = {
  firstName: "No",
  lastName: "Name"
};

to set the default values of the firstName and lastName props.

Then we’ll get the following displayed on the screen:

Jane Smith
Alex Jones
May Wong
No Name

Since we have an empty object in the persons array as the last entry. Therefore, the default values are rendered in place of whatever is passed in.

Conclusion

We can render lists by mapping arrays to components with a map method. In case props aren’t passed into a component, we can set the defaultProps property to set the default values of one or more props.

Finally, we can render components dynamically can map the components by their name string in an object.