Categories
React

Add a Histogram to a React App with the @data-ui/histogram Library

To add a histogram into our React app, we can use the @data-ui/histogram library.

In this article, we’ll look at how to add a histogram to our React app with this library.

Installation

We can install it by running:

npm i @data-ui/histogram

Add a Histogram

We can add a histogram by writing:

import React from "react";
import {
  Histogram,
  DensitySeries,
  BarSeries,
  withParentSize,
  XAxis,
  YAxis
} from "@data-ui/histogram";

const ResponsiveHistogram = withParentSize(
  ({ parentWidth, parentHeight, ...rest }) => (
    <Histogram width={parentWidth} height={parentHeight} {...rest} />
  )
);

const rawData = Array(100).fill().map(Math.random);

export default function App() {
  return (
    <div className="App" style={{ height: 300 }}>
      <ResponsiveHistogram
        ariaLabel="histogram"
        orientation="vertical"
        cumulative={false}
        normalized={true}
        binCount={25}
        valueAccessor={(datum) => datum}
        binType="numeric"
        renderTooltip={({ event, datum, data, color }) => (
          <div>
            <strong style={{ color }}>
              {datum.bin0} to {datum.bin1}
            </strong>
            <div>
              <strong>count </strong>
              {datum.count}
            </div>
            <div>
              <strong>cumulative </strong>
              {datum.cumulative}
            </div>
            <div>
              <strong>density </strong>
              {datum.density}
            </div>
          </div>
        )}
      >
        <BarSeries animated rawData={rawData} />
        <XAxis />
        <YAxis />
      </ResponsiveHistogram>
    </div>
  );
}

We created the ResponsiveHistorgram component to make the histogram fir to the parent’s dimensions.

This is done by calling the withParentSize function to render the histogram with the height of the parent.

In the App component, we use the ResponsiveHistogram component by passing in a few props.

orientation has the orientation of the histogram.

cumulative indicates whether the histogram is cumulative.

normalized sets whether the histogram is normalized as a fraction of the total.

binCount is approximate of the number of bins to use.

renderTooltip is a prop with the function to let us get an entry from the bar we’re hovering on and render them in the tooltip.

bin0 has the bin name.

count has the count of the items in the bin.

cumulative has the cumulative number of items from the leftmost bin to the current bin.

density has the density.

The bars are rendered with the BarSeries component.

animated animates the display of the histogram when it’s loading.

rawData has the raw data.

XAxis adds the x-axis. YAxis adds the y-axis.

Also, we need to specify the height of the histogram container so it fits to the height.

Other properties include the stroke to change the color of the bar.

strokeWidth changes the width of the bar.

DensitySeries

The DensitySeries component lets us plot an estimate of the probability density function.

For example, we can write:

import React from "react";
import {
  Histogram,
  DensitySeries,
  BarSeries,
  withParentSize,
  XAxis,
  YAxis
} from "@data-ui/histogram";

const ResponsiveHistogram = withParentSize(
  ({ parentWidth, parentHeight, ...rest }) => (
    <Histogram width={parentWidth} height={parentHeight} {...rest} />
  )
);

const rawData = Array(100).fill().map(Math.random);

export default function App() {
  return (
    <div className="App" style={{ height: 300 }}>
      <ResponsiveHistogram
        ariaLabel="histogram"
        orientation="vertical"
        cumulative={false}
        normalized={true}
        binCount={25}
        valueAccessor={(datum) => datum}
        binType="numeric"
      >
        <DensitySeries animated rawData={rawData} />
        <XAxis />
        <YAxis />
      </ResponsiveHistogram>
    </div>
  );
}

to add the density series to add the histogram.

Conclusion

We can use the @data-ui/histogram library to add a histogram easily to our React app.

Categories
React

react-i18next NPM Package — Trans Component with Lists and I18nextProvider

If we want to add localization to a React app, we can use the react-i18next NPM package to do it.

In this article, we’ll look at how to use the Trans and I18nextProvider components to render our translations.

Trans Component and Lists

We can use the Trans component with lists.

For example, we can write:

import React from "react";
import i18n from "i18next";
import { initReactI18next, Trans } from "react-i18next";

i18n.use(initReactI18next).init({
  resources: {
    en: {
      translation: {
        list_map: "My dogs are named: <1></1>"
      }
    }
  },
  lng: "en",
  fallbackLng: "en",
  interpolation: {
    escapeValue: false
  }
});

export default function App() {
  return (
    <div className="App">
      <Trans i18nkey="list_map">
        My dogs are named:
        <ul i18nIsDynamicList>
          {["mary", "max"].map((dog) => (
            <li>{dog}</li>
          ))}
        </ul>
      </Trans>
    </div>
  );
}

We have the list_map translation which we load with the Trans component.

i18nkey has the key for the translations.

The i18nIsDynamicList prop lets us render lists in our translations.

Components Array

We can interpolate translations with an array of components.

For example, we can write:

import React from "react";
import i18n from "i18next";
import { initReactI18next, Trans } from "react-i18next";

i18n.use(initReactI18next).init({
  resources: {
    en: {
      translation: {
        hello: "hello great <0>{{what}}</0>"
      }
    }
  },
  lng: "en",
  fallbackLng: "en",
  interpolation: {
    escapeValue: false
  }
});

export default function App() {
  return (
    <div className="App">
      <Trans
        i18nKey="hello"
        defaults="hello <0>{{what}}</0>"
        components={[<strong>{{ what: "universe" }}</strong>]}
      />
    </div>
  );
}

We have an array of components that we passed into the components prop.

The <0> tag indicates the index of the component will be interpolated.

We map the values to the interpolation placeholder with an object.

defaults has the default translation string.

i18nKey has the translation key.

I18nextProvider

We can initialize the i18n instance with the I18nextProvider .

For example, we can write:

index.html

import React from "react";
import ReactDOM from "react-dom";
import App from "./App";
import i18n from "i18next";
import { initReactI18next, I18nextProvider } from "react-i18next";

i18n.use(initReactI18next).init({
  resources: {
    en: {
      translation: {
        hello: "hello world"
      }
    }
  },
  lng: "en",
  fallbackLng: "en",
  interpolation: {
    escapeValue: false
  }
});

const rootElement = document.getElementById("root");
ReactDOM.render(
  <React.StrictMode>
    <I18nextProvider i18n={i18n}>
      <App />
    </I18nextProvider>
  </React.StrictMode>,
  rootElement
);

App.js

import React from "react";
import { useTranslation } from "react-i18next";

export default function App() {
  const { t } = useTranslation();

  return <div className="App">{t("hello")}</div>;
}

The I18nextProvider wraps around the App so that we initial the i18n object for the whole app.

Then in our App component, we can get the translations.

Conclusion

We can use the Trans component to render lists. Also, we have the I18nProvider to wrap around app to enable translations in our whole app.

Categories
React

react-i18next NPM Package — Trans Component

If we want to add localization to a React app, we can use the react-i18next NPM package to do it.

In this article, we’ll look at how to use the Trans component to render our translations.

Trans Component

The Trans component lets render translations that have dynamic text.

For example, we can user it by writing:

import React from "react";
import i18n from "i18next";
import { useTranslation, initReactI18next, Trans } from "react-i18next";

i18n.use(initReactI18next).init({
  resources: {
    en: {
      translation: {
        nameTitle: "mr",
        userMessagesUnread:
          "Hello <1>{{name}}</1>, you have {{count}} unread message. <5>Go to message</5>.",
        userMessagesUnread_plural:
          "Hello <1>{{name}}</1>, you have {{count}} unread messages.  <5>Go to messages</5>."
      }
    }
  },
  lng: "en",
  fallbackLng: "en",

interpolation: {
    escapeValue: false
  }
});

const count = 2;
const name = "james";

export default function App() {
  const { t } = useTranslation();

  return (
    <div className="App">
      <Trans i18nKey="userMessagesUnread" count={count}>
        Hello <strong title={t("nameTitle")}>{{ name }}</strong>, you have
        {{ count }} unread message. <a href="msgs">Go to messages</a>
      </Trans>
    </div>
  );
}

We set the i18nKey to the translation key to get the item.

count passes th count value to the item.

Also, we render the nameTitle translation inside the Trans tags.

The positions of the text will automatically be matched by react-i18next to render the translations in the right places.

We can also pass in the values we interpolate as props.

For example, we can write:

import React from "react";
import i18n from "i18next";
import { useTranslation, initReactI18next, Trans } from "react-i18next";

i18n.use(initReactI18next).init({
  resources: {
    en: {
      translation: {
        hello:
          "hello <italic>beautiful beautiful</italic> <bold>{{what}}</bold>"
      }
    }
  },
  lng: "en",
  fallbackLng: "en",

interpolation: {
    escapeValue: false
  }
});

export default function App() {
  return (
    <div className="App">
      <Trans
        i18nKey="hello"
        defaults="hello <italic>beautiful</italic> <bold>{{what}}</bold>"
        values={{ what: "world" }}
        components={{ italic: <i />, bold: <strong /> }}
      ></Trans>
    </div>
  );
}

We have the Trans component with the trannslation added to it.

The defaults prop has the default translation to render if the translation with the given i18nkey isn’t found.

values has the object with the values, we interpolate into the curly braces.

components has the components that we want to interpolate in place of the tags with the given name.

We can also use some simple elements directly in our translations.

For example, we can write:

import React from "react";
import i18n from "i18next";
import { useTranslation, initReactI18next, Trans } from "react-i18next";

i18n.use(initReactI18next).init({
  resources: {
    en: {
      translation: {
        hello: "Hello <1>{{name}}</1>."
      }
    }
  },
  lng: "en",
  fallbackLng: "en",
  interpolation: {
    escapeValue: false
  }
});

const name = "james";

export default function App() {
  return (
    <div className="App">
      <Trans i18nkey="hello">
        Hello <strong>{{ name }}</strong>.
      </Trans>
    </div>
  );
}

We put the HTML strong element between the tags and it’ll be rendered.

It’ll also get the correct translation for plurals automatically:

import React from "react";
import i18n from "i18next";
import { initReactI18next, Trans } from "react-i18next";

i18n.use(initReactI18next).init({
  resources: {
    en: {
      translation: {
        newMessages: "You got one message.",
        newMessages_plural: "You got {{count}} messages."
      }
    }
  },
  lng: "en",
  fallbackLng: "en",
  interpolation: {
    escapeValue: false
  }
});

const messages = ["message one", "message two"];

export default function App() {
  return (
    <div className="App">
      <Trans i18nkey="newMessages" count={messages.length}>
        You got {{ count: messages.length }} messages.
      </Trans>
    </div>
  );
}

We set the i18nkey to newMessages and set the count to the length of messages .

Then we get get the correct translation according to whether messages.length is 1 or not 1.

The _plural suffix indicates the plural version of the translation without the suffix.

Conclusion

We can use the Trans component to render HTML and plural translations.

Categories
React

react-i18next NPM Package — withTranslation

If we want to add localization to a React app, we can use the react-i18next NPM package to do it.

In this article, we’ll look at how to load translations with the withTranslation higher-order component.

withTranslation

The withTranslation higher-order component lets us wrap our component to let us gain access to the t function and i18n object.

For example, we can write:

import React from "react";
import i18n from "i18next";
import { initReactI18next, withTranslation } from "react-i18next";

const resources = {
  en: {
    ns1: {
      "Welcome to React": "Welcome to React and react-i18next"
    }
  }
};

i18n.use(initReactI18next).init({
  resources,
  lng: "en",
  keySeparator: false,
  interpolation: {
    escapeValue: false
  }
});

function App({ t }) {
  return (
    <div className="App">
      <p>{t("Welcome to React")}</p>
    </div>
  );
}

export default withTranslation("ns1")(App);

We called the withTranslation higher-order component with the namespace to load the ns1 translation namespace.

Also, we can load multiple namespaces with it.

For example, we can write:

import React from "react";
import i18n from "i18next";
import { initReactI18next, withTranslation } from "react-i18next";

const resources = {
  en: {
    ns1: {
      "Welcome to React": "Welcome to React and react-i18next"
    },
    ns2: {
      Hello: "Hello World"
    }
  }
};

i18n.use(initReactI18next).init({
  resources,
  lng: "en",
  keySeparator: false,
  interpolation: {
    escapeValue: false
  }
});

function App({ t }) {
  return (
    <div className="App">
      <p>{t("Welcome to React")}</p>
      <p>{t("ns2:Hello")}</p>
    </div>
  );
}

export default withTranslation(["ns1", "ns2"])(App);

to load the ns1 and ns2 namespaces.

Any namespace after the first needs the namespace name.

Overriding the i18next Instance

We can override the i18next instance, by passing an object to the i18n prop:

import React from "react";
import i18n from "i18next";
import { initReactI18next, withTranslation } from "react-i18next";

const resources = {
  en: {
    ns1: {
      "Welcome to React": "Welcome to React and react-i18next"
    },
    ns2: {
      Hello: "Hello World"
    }
  }
};

i18n.use(initReactI18next).init({
  resources,
  lng: "en",
  keySeparator: false,
  interpolation: {
    escapeValue: false
  }
});

const MyComponent = ({ t }) => {
  return (
    <div className="App">
      <p>{t("Welcome to React")}</p>
    </div>
  );
};

const ExtendedComponent = withTranslation("ns1")(MyComponent);

export default function App() {
  return (
    <div className="App">
      <ExtendedComponent i18n={i18n} />;
    </div>
  );
}

We pass it into the ExtendedComponent which is created from the withTranslation component.

Also, we can disable the use of the Suspense component with the useSuspense prop.

For example, we can write:

import React from "react";
import i18n from "i18next";
import { initReactI18next, withTranslation } from "react-i18next";

const resources = {
  en: {
    translation: {
      "Welcome to React": "Welcome to React and react-i18next"
    }
  }
};

i18n.use(initReactI18next).init({
  resources,
  lng: "en",
  keySeparator: false,
  interpolation: {
    escapeValue: false
  }
});

const MyComponent = ({ t, tReady }) => {
  return (
    <div className="App">
      <p>{tReady && t("Welcome to React")}</p>
    </div>
  );
};

const ExtendedComponent = withTranslation()(MyComponent);

export default function App() {
  return (
    <div className="App">
      <ExtendedComponent useSuspense={false} />
    </div>
  );
}

If we set useSuspense to false , then we have to use the tReady prop to check if the translation is ready.

Conclusion

The react-i18next NPM package has the withTranslation higher-order component to provide the required translations functions and objects via the props.

Categories
React

react-i18next NPM Package — Translation Component

If we want to add localization to a React app, we can use the react-i18next NPM package to do it.

In this article, we’ll look at how to use the Translation component to render our translations.

Translation (render prop)

The Translation component lets us pass in a function as the render prop to render the translations.

For example, we can write:

import React from "react";
import i18n from "i18next";
import { initReactI18next, Translation } from "react-i18next";

const resources = {
  en: {
    translation: {
      "Welcome to React": "Welcome to React and react-i18next"
    }
  }
};

i18n.use(initReactI18next).init({
  resources,
  lng: "en",
  keySeparator: false,
  interpolation: {
    escapeValue: false
  }
});

export default function App() {
  return (
    <div className="App">
      <Translation>
        {(t, { i18n }) => <p>{t("Welcome to React")}</p>}
      </Translation>
    </div>
  );
}

to render the translation.

We also have access to the i18n object to let us do things like changing the language:

import React from "react";
import i18n from "i18next";
import { initReactI18next, Translation } from "react-i18next";

const resources = {
  en: {
    translation: {
      "Welcome to React": "Welcome to React and react-i18next"
    }
  },
  fr: {
    translation: {
      "Welcome to React": "Bienvenue dans React et react-i18next"
    }
  }
};

i18n.use(initReactI18next).init({
  resources,
  lng: "en",
  keySeparator: false,
  interpolation: {
    escapeValue: false
  }
});

export default function App() {
  return (
    <div className="App">
      <Translation>
        {(t, { i18n }) => (
          <p>{i18n.changeLanguage("fr") && t("Welcome to React")}</p>
        )}
      </Translation>
    </div>
  );
}

We change the language on the fly and also render the translation afterward.

Loading Namespaces

We can load namespaces with the ns prop.

For example, we can write:

import React from "react";
import i18n from "i18next";
import { initReactI18next, Translation } from "react-i18next";

const resources = {
  en: {
    ns1: {
      "Welcome to React": "Welcome to React and react-i18next"
    }
  }
};

i18n.use(initReactI18next).init({
  resources,
  lng: "en",
  keySeparator: false,
  interpolation: {
    escapeValue: false
  }
});

export default function App() {
  return (
    <div className="App">
      <Translation ns="ns1">
        {(t) => <p>{t("Welcome to React")}</p>}
      </Translation>
    </div>
  );
}

We have the ns1 namespace.

And we set the ns prop to 'ns1' so that we can load the translations from there.

We can also pass in an array as the value of ns :

import React from "react";
import i18n from "i18next";
import { initReactI18next, Translation } from "react-i18next";

const resources = {
  en: {
    ns1: {
      "Welcome to React": "Welcome to React and react-i18next"
    },
    ns2: {
      Hello: "Hello World"
    }
  }
};

i18n.use(initReactI18next).init({
  resources,
  lng: "en",
  keySeparator: false,
  interpolation: {
    escapeValue: false
  }
});

export default function App() {
  return (
    <div className="App">
      <Translation ns={["ns1", "ns2"]}>
        {(t) => <p>{t("ns2:Hello")}</p>}
      </Translation>
    </div>
  );
}

We load 2 namespaces, and we add the namespace name before the translation key so that the translation will be found.

For example, we can write:

import React from "react";
import i18n from "i18next";
import { initReactI18next, Translation } from "react-i18next";

const resources = {
  en: {
    translation: {
      "Welcome to React": "Welcome to React and react-i18next"
    }
  }
};

i18n.use(initReactI18next).init({
  resources,
  lng: "en",
  keySeparator: false,
  interpolation: {
    escapeValue: false
  }
});

export default function App() {
  return (
    <div className="App">
      <Translation i18n={i18n}>
        {(t) => <p>{t("Welcome to React")}</p>}
      </Translation>
    </div>
  );
}

We set the i18n prop to the i18n instance we want.

Conclusion

We can use the Translation component from the react-i18next NPM package to load the translations.