Categories
React Answers

How to Add Refs to React Components by Forwarding Refs?

Sometimes, we want to add refs to React components.

In this article, we’ll look at how to add refs to React components.

Add Refs to React Components by Forwarding Refs

Forwarding refs means that we are getting the refs from a child component from a parent component.

For instance, if we want to get the ref of a button that resides in a custom button component, we can write the following code:

import React, { useEffect } from "react";

const FancyButton = React.forwardRef((props, ref) => (
  <button ref={ref}>{props.children}</button>
));

export default function App() {
  const buttonRef = React.createRef();

  useEffect(() => {
    buttonRef.current.focus();
  }, []);

  return (
    <>
      <FancyButton ref={buttonRef}>Click me!</FancyButton>;
    </>
  );
}

In the code above, we have the FancyButton component, which has the button element, which we want to access. To let us access it from App or another component, we call React.forwardRef , which takes a callback with 2 parameters, props and ref .

The props have the props, and the ref is the ref that we can access from the outside. We set the ref prop to the ref parameter so to set the ref to the button.

Then in App , we create the buttonRef and pass it into ref . Then in the useEffect callback, we call buttonRef.current.focus(); to focus the button when App load since we have an empty array as the 2nd argument.

Forwarding refs are also used with 3rd party components. For instance, if we have to use the react-hook-form package and we’re using our own custom input control components, then we have to call forwardRef as follows:

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

const Select = React.forwardRef(({ label }, ref) => (
  <>
    <label>{label}</label>
    <select name={label} ref={ref}>
      <option value="10">10</option>
      <option value="20">20</option>
    </select>
  </>
));

export default function App() {
  const { register, handleSubmit } = useForm();

  const onSubmit = () => {};

  return (
    <>
      <form onSubmit={handleSubmit(onSubmit)}>
        <Select label="Age" ref={register} />
        <input type="submit" />
      </form>
    </>
  );
}

In the code above, we created a custom select control called Select , which is created by calling forwardRef with a callback that takes the ref as the 2nd parameter, we set it as the value of the ref prop in the select element.

Then we can access the ref of select from App .

Conclusion

Forwarding refs means that we are getting the refs from a child component from a parent component.

Categories
React Answers

How to Use Prop Types to Check to Validate React Compoennt Prop Data

Checking data types for React component props lets us prevent many mistakes in our code.

In this article, we’ll look at how to check data types for React component props.

Use Prop Types to Check to Validate React Compoennt Prop Data

By default, React lets us pass anything from parent components to child components via props. This isn’t ideal because it’s very easy to make a mistake that may cause runtime errors in production.

Therefore, we should use React’s built-in prop-type validation feature to check the data type of props. We can also use it to check if the prop value has the format that we want them to be in.

There’s built-in prop type for common JavaScript data types. In addition, we can check for a combination of one or more types and we can also pass in a custom validation to check for the prop data.

For instance, we can use it as follows:

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

const Foo = ({ data }) => {
  return <p>{data}</p>;
};

Foo.propTypes = {
  data: PropTypes.string
};

export default function App() {
  return <Foo data="bar" />;
}

In the code above, we have:

Foo.PropTypes = {
  data: PropTypes.string
};

to check that the data prop is indeed a string. In the code above, we passed in a string as the value of the data prop. Therefore, we should see the p element displayed with the text ‘bar’ inside.

Otherwise, we would get an error.

We can add our own prop data validation as follows:

import React from "react";

const Foo = ({ data }) => {
  return <p>{data}</p>;
};

Foo.propTypes = {
  data(props, propName, componentName) {
    if (!/bar/.test(props[propName])) {
      return new Error("I want bar");
    }
  }
};

export default function App() {
  return <Foo data="baz" />;
}

In the code above, we have:

Foo.propTypes = {
  data(props, propName, componentName) {
    if (!/bar/.test(props[propName])) {
      return new Error("I want bar");
    }
  }
};

Therefore, if we didn’t pass in 'bar' as the value of the data prop into Foo , we’ll get the error ‘I want bar’ logged in the console. We pass in 'baz' , so we’ll get the error.

Conclusion

By default, React lets us pass anything from parent components to child components via props. This isn’t ideal because it’s very easy to make a mistake that may cause runtime errors in production.

Therefore, we should use React’s built-in prop-type validation feature to check the data type of props. We can also use it to check if the prop value has the format that we want them to be in.

Categories
React Answers

How to Use React Error Boundaries to Handle Errors Gracefully?

We can use React error boundaries to handle errors gracefully in a React app.

In this article, we’ll look at how to use React error boundaries to handle errors gracefully in a React app.

Use React 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.

Conclusion

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.

Categories
React Answers

How to Set Focus On Input After Render in a React Component?

Sometimes, we want to set focus on an input element in a React component after rendering it.

In this article, we’ll look at how to set focus on an input element in a React component after rendering it.

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.

Conclusion

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.

Categories
React Answers

How to Set React Component Default Prop Values?

Sometimes, we want to set default values for React component props.

In this article, we’ll look at how to set default values for React component props.

Set React Component Default Prop Values

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 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.