React Development: Web Document Management App

Dynamic Web TWAIN is a JavaScript library designed for document scanning and document management. This tutorial guides through React development. You will see how to combine Reactjs and Dynamic Web TWAIN to build a simple web application which can acquire images from a document scanner and load images from local hard drive.

React web document scanning

What You Should Know About Dynamic Web TWAIN

Making Web Document Management App Using React

In the following paragraphs, we will create the skeleton of a React project first and then integrate Dynamic Web TWAIN into the project to implement document scanning and management.

Getting Started with a New React Project

To create a new React project, you can choose one of the following ways:

npm

npm install -g create-react-app
create-react-app document-scan

npx

npx create-react-app document-scan

Yarn

yarn create react-app document-scan

Implementing Document Scanning with Dynamic Web TWAIN SDK

Install dependent packages via npm command:

npm install dwt@17.0.2
npm install @babel/core @babel/preset-env
npm i ncp -g

Dynamic Web TWAIN SDK consists of platform-specific service applications (for scanner communication) and JavaScript library files, which are located in the node_modules/dwt/dist folder for programming and distribution. We use ncp to copy resources to the public folder of the React project:

ncp node_modules/dwt/dist public/dwt-resources

The next step is to create a React component in DynamsoftSDK.js:

import React from 'react';
import Dynamsoft from 'dwt';

export default class DWT extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            scanners: [],
            currentScanner: "Looking for devices.."
        };
        this.DWObject = null;
        this.containerId = 'dwtcontrolContainer';
        this.width = "100%";
        this.height = "600";
    }

    componentDidMount() {

    }

    render() {
        return (
           
        );
    }
}

In componentDidMount(), we set the resource path for initializing the Dynamic Web TWAIN object. As the OnWebTwainReady event is trigged, we can get the information of connected document scanners and then update relevant UI elements:

componentDidMount() {
    Dynamsoft.DWT.RegisterEvent('OnWebTwainReady', () => {
        this.DWObject = Dynamsoft.DWT.GetWebTwain(this.containerId);
        if (this.DWObject) {
            let vCount = this.DWObject.SourceCount;
            let sourceNames = [];
            for (let i = 0; i < vCount; i++)
                sourceNames.push(this.DWObject.GetSourceNameItems(i));
            this.setState({ scanners: sourceNames });
        }
    });
    this.loadDWT();
}

loadDWT() {
    Dynamsoft.DWT.ProductKey = this.props.productKey;
    Dynamsoft.DWT.ResourcesPath = "dwt-resources";
    Dynamsoft.DWT.Containers = [{ ContainerId: this.containerId, Width: this.width, Height: this.height }];
    let checkScriptLoaded = () => {
        if (Dynamsoft.Lib.detect.scriptLoaded) {
            Dynamsoft.DWT.Load();
        } else {
            setTimeout(() => {
                checkScriptLoaded();
            }, 1000);
        }
    };
    checkScriptLoaded();
}

Because of lazy loading, checking SDK loading status is necessary.

Let’s create the UI layout in render():

render() {
    return (
        <div style={{ width: "30%", margin: "0 auto" }}>
            <select style={{ width: "100%" }} tabIndex="1" value={this.state.currentScanner} onChange={(e) => this.onSourceChange(e.target.value)}>
                {
                    this.state.scanners.length > 0 ?
                        this.state.scanners.map((_name, _index) =>
                            <option value={_name} key={_index}>{_name}</option>
                        )
                        :
                        <option value="Looking for devices..">Looking for devices..</option>
                }
            </select>
            <button tabIndex="2" style={{ marginRight: "4%", width: "48%" }}
                onClick={() => this.acquireImage()}
                disabled={this.state.scanners.length > 0 ? "" : "disabled"}
            >Scan</button>
            <button tabIndex="3" style={{ margin: "2% 0", width: "48%" }}
                onClick={() => this.loadImagesOrPDFs()}
            >Load</button>
            <div id={this.containerId}></div>
        </div >
    );
}

There are two buttons, one for acquiring images from document scanners, and the other for loading images from local hard drive. The corresponding code implementation of button click event is as follows:

acquireImage() {
    this.DWObject.CloseSource();
    for (let i = 0; i < this.DWObject.SourceCount; i++) {
        if (this.DWObject.GetSourceNameItems(i) === this.state.currentScanner) {
            this.DWObject.SelectSourceByIndex(i);
            break;
        }
    }
    this.DWObject.OpenSource();
    this.DWObject.AcquireImage();
}

loadImagesOrPDFs() {
    this.DWObject.IfShowFileDialog = true;
    this.DWObject.Addon.PDF.SetResolution(200);
    this.DWObject.Addon.PDF.SetConvertMode(1);
    this.DWObject.LoadImageEx("", 5,
        () => { },
        (errorCode, errorString) => alert(errorString));
}

Once the component is ready, we can add it to App.js:

import logo from './logo.svg';
import DWTLogo from './icon-dwt.svg';
import DynamsoftLogo from './logo-dynamsoft-white-159X39.svg';
import './App.css';
import DWT from './DynamsoftSDK';

function App() {
  return (
    <div className="App">
      <header className="App-header">
        <a href="https://www.dynamsoft.com/web-twain/overview/" target="_blank" rel="noopener noreferrer" ><img src={DWTLogo} className="dwt-logo" alt="Dynamic Web TWAIN Logo" /></a>
        <div style={{ width: "10px" }}></div>
        <a href="https://reactjs.org/" target="_blank" rel="noopener noreferrer" ><img src={logo} className="App-logo" alt="logo" /></a>
        <div style={{ width: "18%" }}></div>
        <a href="https://www.dynamsoft.com" target="_blank" rel="noopener noreferrer" ><img src={DynamsoftLogo} className="ds-logo" alt="Dynamsoft Logo" /></a>
      </header>
      <main className="App-main">
        <DWT
          productKey="DLS2eyJoYW5kc2hha2VDb2RlIjoiMjAwMDAxLTE2NDk4Mjk3OTI2MzUiLCJvcmdhbml6YXRpb25JRCI6IjIwMDAwMSIsInNlc3Npb25QYXNzd29yZCI6IndTcGR6Vm05WDJrcEQ5YUoifQ=="
        />
      </main>
    </div>
  );
}

export default App;

To make the SDK work successfully, you need to apply for a 30-day FREE trial license and update the line:

productKey="DLS2eyJoYW5kc2hha2VDb2RlIjoiMjAwMDAxLTE2NDk4Mjk3OTI2MzUiLCJvcmdhbml6YXRpb25JRCI6IjIwMDAwMSIsInNlc3Npb25QYXNzd29yZCI6IndTcGR6Vm05WDJrcEQ5YUoifQ=="

Now, the simple web document management app is finished. We can run npm start to launch the app:

npm start

React web document management

Source Code

https://github.com/yushulx/web-twain-react-simple