Create a React.js CSV Importer in Minutes

author-avatar

Flatirons Fuse is a powerful embedded CSV import tool that makes importation painless.

Getting Started: Creating a Template

To begin, we must first register an account in the Flatirons Fuse app here, after which we can go to the Templates page and build our first Template. A Template represents the fields that your own system accepts, also known as your data schema. We will call our Template “Customer List” as shown below:

For the sake of this example, let’s add two columns to our Template, Customer Name and Customer Email, as seen below:

The “internal key” must be specified to match the column key in your data schema, column label is used to show in our spreadsheet and match the CSV header, and for column type, we can choose many different data types, and the required checkbox marks our column as required.

So for our column “Customer Email”, we must use the “Email” data type. This will ensure that when your customers upload data, they upload valid emails. For “Customer Name”, we can just use “String” as a data type like below. Let’s mark both as required.

 

Template Columns

Now we’re ready to start coding. As you can see, it is very easy to create templates and columns on Flatirons Fuse.

Installing the React CSV Importer: fuse-importer

To get started with any react project, we simply need to utilize our favorite package management tool to add the fuse-importer requirement.

yarn add fuse-importer

Creating our CSV Importer Component

We need to set up the flatirons fuse importer using our Template ID and Organization API Key. You can get them on the Templates page.

import React from "react";
import FuseImporter from "fuse-importer";

const CSVImporterComponent = () => {
 function showImporter() {
   const organizationApiKey = "YOUR ORGANIZATIONS API KEY";
   const templateId = "YOUR TEMPLATE ID";
   const importer = new FuseImporter(organizationApiKey, templateId);

   importer.onValidateRecord = async (record) => {
     // return no frontend validation errors
     return {};
   };

   importer.onSubmit = async (records) => {
     // an empty hash will tell us the import was successful!
     return {
       message: "Your data was imported successfully",
       errors: {},
     };
   };

   importer.show();
 }

 return <button onClick={showImporter}>Show Importer</button>;
};

export default CSVImporterComponent;

Setup the Required Hooks

Our importer instance needs two required hooks to get to work; onSubmit and onValidateRecord. Don’t worry about them now. We’ll explain the hooks later. For now, we just need to call the method “show” in our importer instance to use it.

Now we are ready to use our CSVImporterComponent at any place in our app. I’ll include this in my App component.

import logo from "./logo.svg";
import "./App.css";
import CSVImporterComponent from "./CSVImporterComponent";

const App = () => {
 return (
   <div className="App">
     <header className="App-header">
       <img src={logo} className="App-logo" alt="logo" />
       <CSVImporterComponent />
     </header>
   </div>
 );
}

export default App;

Now when we click on the “Show Importer” button, we can see the Flatirons Fuse Importer working.

As you can see on the right hand side, the list of required fields is listed for the user. Now, we can test our importer using a CSV file:

first_name,email
grady,gcrathorne0@flatironsfuse.com
kevyn,ksprowell1@wordpress.com
barr,bterese2@flatironsfuse.com
lonna,lcaslake3@flatironsfuse.com
shannon,sbrackenridge4@flatironsfuse.com
emilie,etregensoe5@flatironsfuse.com
toiboid,tmersey6@flatironsfuse.com
jourdain,jgiraudou7@flatironsfuse.com
garvy,gspendlove8@flatironsfuse.com
gregoire,gspensly9@flatironsfuse.com

 

Check if everything is OK, and click on “Yes, continue”.

Here we can see Flatirons Fuse match our columns with template columns. Just click on “Continue”.

In the last step, we can review our data before submitting it. Let’s make things more complex and implement some custom validations before submitting.

Performing Data Transformations when Loading CSV Data

When the csv importer is initialized, you have the chance to transform data. For example, let’s say that your system wants all customer_name’s to be capitalized. Instead of adding a validation and requiring the user to go through each row and capitalize the first letter, you can use the formatRecord hook to do this on your user’s behalf. Here’s an example:

importer.formatRecord = (record) => {
 const newRecord = { ...record };

 // capitalize first letter in customer_name
 if (typeof newRecord.customer_name === "string") {
   newRecord.customer_name =
     newRecord.customer_name.charAt(0).toUpperCase() +
     newRecord.customer_name.slice(1);
 }

 return newRecord;
};

Adding Custom Front-end Validations before Submitting

If data transformations aren’t enough, you can add custom validations to your react csv importer that users must follow before submitting data. For the sake of this example, we will introduce a rule that ensures that all uploaded emails must end with “@flatironsfuse.com”. Let’s see how easy it is. To do this, we have to implement a custom logic inside the onValidateRecord hook.

importer.onValidateRecord = async (record) => {
 const errors = {};
 const customerEmail = record["customer_email"];
 if (customerEmail && !customerEmail.endsWith("@flatironsfuse.com")) {
   errors["customer_email"] = "The email must ends with @flatironsfuse.com";
 }
 return errors;
};

If we re-upload our CSV file, an invalid row will appear as follows:

Adding Custom Backend Validations on Submit

Flatirons Fuse allows us to validate our data on the back-end in a simple way. To do this, we should use the onSubmit hook. Every single record passed to the onSubmit function has a 

records[0]._meta.id

If you have an issue with a record on the backend, you can respond to the request with this id and an error message and we will show the user how to correct the issue. For example, let’s say that we need to ensure that all of our emails must be unique in our database. Again, for the sake of providing an example, imagine that someone imports a CSV that contains an email that already exists in your database.

We’ll use a fake backend call for testing purposes.

async function fakeBackendValidation(records) {
 // in this function you would actually submit records to your backend
 return new Promise((resolve) => {
   setTimeout(() => {
     resolve({
       message:
         "Most rows were imported. We found a few errors. Please fix them and re-submit",
       errors: {
         [records[0]._meta.id]: {
           customer_email: "Email is already taken. Emails must be unique.",
         },
       },
     });
   }, 1000);
 });
}

 

importer.onSubmit = async (records) => {
   return await fakeBackendValidation(records);
};

When we try to re-upload our data, we can get this validation.

All done. Our final component should look like this:

import React from "react";
import FuseImporter from "fuse-importer";

async function fakeBackendValidation(records) {
  // in this function you would actually submit records to your backend
 return new Promise((resolve) => {
   setTimeout(() => {
     resolve({
       message: "Most rows were imported. We found a few errors. Please fix them and re-submit",
       errors: {
         [records[0]._meta.id]: {
           customer_email: "Email is already taken. Emails must be unique.",
         },
       },
     });
   }, 1000);
 });
}

const CSVImportComponent = () => {
 function showImporter() {
   const organizationApiKey = "YOUR ORGANIZATIONS API KEY";
   const templateId = "YOUR TEMPLATE ID";

   if (
     organizationApiKey.indexOf("YOUR") !== -1 ||
     templateId.indexOf("YOUR") !== -1
   ) {
     window.confirm(
       "You need to configure your organization api key and template id."
     );
     return;
   }


   const importer = new FuseImporter(organizationApiKey, templateId);

   importer.onValidateRecord = async (record) => {
     const errors = {};
     const customerEmail = record["customer_email"];
     if (customerEmail && !customerEmail.endsWith("@flatironsfuse.com")) {
       errors["customer_email"] =
         "The email must ends with @flatironsfuse.com";
     }
     return errors;
   };

   importer.formatRecord = (record) => {
     const newRecord = { ...record };

     // capitalize first letter in customer_name
     if (typeof newRecord.customer_name === "string") {
       newRecord.customer_name =
         newRecord.customer_name.charAt(0).toUpperCase() +
         newRecord.customer_name.slice(1);
     }

     return newRecord;
   }
  
   importer.onSubmit = async (records) => {
     return await fakeBackendValidation(records);
   };

   importer.show();
 }

 return <button onClick={showImporter}>Show Importer</button>;
};

export default CSVImportComponent;

With your importer and custom validations/transformations set up, the only thing left to do is to customize (brand) your importer.

Customize the CSV Importer

Your React.js CSV and Spreadsheet importer would not be complete without the option to customize it to match your site or application. Our Get Started guide allows you to customize your importer to match your branding for a seamless experience. Simply click the Customize Importer button, or click Branding in the left-hand menu. 

On the Branding page, you can customize colors, add a logo, set a background, all to better match your solution, ensuring your Angular.js Spreadsheet and CSV importer is just that – yours.

You can get a sneak peek from your customer’s viewpoint by going back to the Templates screen, and clicking the Preview link.

Here you can see the logo applied, and the colors selected.

You can even preview the functionality by dragging and dropping a .CSV file, or by clicking browse files. 

Creating a seamless user experience is our main goal, and an intuitive flow and strong validation/transformation capacity is a key part of that. We hope our branding and customization features can deliver the final piece of the puzzle, ensuring that your newly configured CSV importer is just that – yours.