React Tips — Setting State and Internationalization

John Au-Yeung - Jan 23 '21 - - Dev Community

Check out my books on Amazon at https://www.amazon.com/John-Au-Yeung/e/B08FT5NT62

Subscribe to my email list now at http://jauyeung.net/subscribe/

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 set multiple states sequentially and the internationalization of React apps.

setState Updater Function

In React class-based components, the setState method either takes an object with the state to update or a function.

setState also takes a function, which preserves the order of how the state should be applied as well as making sure that all previous states are flushed through.

For instance, we can call setState with a callback function instead of an object as follows:

import React, { Suspense } from "react";

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

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

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

  render() {
    return (
      <>
        <button onClick={this.increment.bind(this)}>Increment</button>
        <p>{this.state.count}</p>
      </>
    );
  }
}
Enter fullscreen mode Exit fullscreen mode

In the code above, we have the increment method, which first increases the count by 1, then it increases the count again by 2.

Since we passed in a callback function to setState , count should increase by 3 every time that we click the Increment as the state changes are applied sequentially.

Use Prop Types to Check to Validate 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" />;
}
Enter fullscreen mode Exit fullscreen mode

In the code above, we have:

Foo.PropTypes = {
  data: PropTypes.string
};
Enter fullscreen mode Exit fullscreen mode

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" />;
}
Enter fullscreen mode Exit fullscreen mode

In the code above, we have:

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

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.

Internationalization

The react-intl library is great for internationalization of React apps. It’s made by Yahoo. It has lots of components for doing various things like formatting dates for a specific locale, pluralization and more.

We can install it by running:

npm i react-intl
Enter fullscreen mode Exit fullscreen mode

For instance, we can use it as follows:

import React from "react";
import { IntlProvider, FormattedDate } from "react-intl";

export default function App() {
  return (
    <IntlProvider locale="fr">
      <FormattedDate value={new Date(2019, 0, 1)} weekday="long" />
    </IntlProvider>
  );
}
Enter fullscreen mode Exit fullscreen mode

In the code above, we referenced the IntlProvider component from react-intl , and inside it, we have the FormattedDate component to format the date that’s passed into the value prop.

Then we should see ‘ mardi’ on the screen because we specified that the locale is 'fr' , which is French.

react-intl has many other components that we can use to make internalization easy, so we should use this instead of writing the code ourselves.

Conclusion

Setting state in a component is easier if we pass in a callback function instead of an object. This is because the setting of the states will be done sequentially instead of at an indeterminate time. This makes running setState multiple times easy if we need to set them sequentially.

To make passing props less error-prone, we should use prop-types to check for the correct prop type and format when props are being passed in. React will log errors to the console the type or format doesn’t match what we specified.

Finally, the internationalization of Reach apps is easy if we use the react-intl library. It has components for doing things like formatting dates and pluralization for different locales.

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .