DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports Events Over 2 million developers have joined DZone. Join Today! Thanks for visiting DZone today,
Edit Profile Manage Email Subscriptions Moderation Admin Console How to Post to DZone Article Submission Guidelines
View Profile
Sign Out
Refcards
Trend Reports
Events
Zones
Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
  1. DZone
  2. Software Design and Architecture
  3. Cloud Architecture
  4. Building a React Front-End for my AWS Lambda Sudoku Solver

Building a React Front-End for my AWS Lambda Sudoku Solver

Learn how to build your own AWS Lambda sudoku solver with React!

Kevin Hooke user avatar by
Kevin Hooke
·
Apr. 26, 19 · Tutorial
Like (1)
Save
Tweet
Share
8.75K Views

Join the DZone community and get the full member experience.

Join For Free

Over the past few months, I built an implementation of Donald Knuth’s Algorithm X using Dancing Links in Java to solve Sudoku puzzles.

This was a fascinating exercise in itself (you can read more my experience here), but the next logical step would be to package it up in a way to share it online.

Since I’m pursuing my AWS certifications right now, one interesting and low-cost approach to host the Solver implementation is to package it as an AWS Lambda. Sudoku Solver as a Service? Done. I exposed it through AWS API Gateway. It accepts a request payload that looks like this:

{"rows":["...81.67.","..749.2.8",".6..5.1.4","1....39..","4...8...7","..69....3","9.2.3..6.","6.1.743..",".34.69..."]}


and returns a response with a solution to the submitted puzzle request like this:

{"rows":["349812675","517496238","268357194","185723946","493681527","726945813","972538461","651274389","834169752"]}


The request and response payloads are an array of Strings, where each item represents a String of values concatenated together for one row in the grid, with ‘.’s for unknowns.

I’m still learning React as I go, and while building this front-end for my Lambda Sudoku Solver, I learned some interesting things about React and JavaScript. The source for the app is shared here.

I used Flux to structure the app, so the main parts of the app are:

  • A main, high-level Container component
  • A CellComponent that renders each cell in the Sudoku grid
  • An Action that handles the interaction with AWS Lambda
  • A Store that holds the results from calling the Lambda

I don’t want to focus on the pros and cons of using React or Flux (and this is not intended to be a how-to on building an app using React) as there were some other specific issues I ran into that were interesting learning opportunities. A couple of these I already captured in separate posts, so I’ll include these links below.

Iteration 1: onChange Handler Per Row

My first approach to maintaining the state for the display of the grid and the handler for changes to each cell was to keep it simple and have a separate array of values per row and a separateonChange handler for each row. This is not a particularly effective way to structure this as there’s duplication in each of the nine handlers.

The State looked like this:

this.state =
    {
        row1 : [],
        row2 : [],
        row3 : [],
        row4 : [],
        row5 : [],
        row6 : [],
        row7 : [],
        row8 : [],
        row9 : []
    };


And each of the handlers looked like this, one handler per row, so handleChangeRow1() through  handleChangeRow9():

handleChangeRow1(index, event){
    console.log("row 1 update: " + event.target.value);
    var updatedRow = [...this.state.row1];
    updatedRow[index] = event.target.value
    this.setState( { row1 : updatedRow } );
}


This approach needed nine versions of the function above, each one specifically handling updates to the state for a single row. We’ll come back to improve a bit this later.

The interesting thing to notice, at this point, is that to update an array in a React state, you need to clone a copy of the array, and then update the copy. I used the spread operator ‘…’ to clone the array.

Each row in the grid I rendered separately like this (so this approach needed nine of these blocks):

<div>
    {
        this.state.row1.map( (cell, index) => (
            <CellComponent key={index} value={this.state.row1[index]}
                           onChange={this.handleChangeRow1.bind(this, index)}/>
            )
        )}
</div>


This was my first working version of the app, at least at the point where I could track the State of the grid as a user entered or changed values in the 9×9 grid. Next steps were to improve the approach.

Iteration 2: Using an Array of Arrays for the State

The first improvement was to improve the State arrays, moving to an array of arrays. This is easily set up like this:

this.state =
    {
        grid: []
    };

for (var row = 0; row < 9; row++) {
    this.state.grid[row] = [];
}


Iteration 3: One onChange Handler for All Rows

Instead of a handler per row, I parameterized the onChange handler to reuse for all rows. This is what I ended up with:

handleGridChange(row, colIndex, event) {
    console.log("row [" + row + "] col [" + colIndex + "] : " + event.target.value);
    var updatedGrid = [...this.state.grid];
    updatedGrid[row][colIndex] = event.target.value;

    //call Action to send updated data to Store
    SudokuSolverAction.updatePuzzleData(updatedGrid);
}


Using .map() on each of the rows in State, I then rendered each row of the grid like this, passing the current row index and column index as params into handleGridChange():

<tr>
    {
        this.state.grid[0].map((cell, colIndex) => (
                <td key={"row0" + colIndex}>
                    <CellComponent value={this.state.grid[0][colIndex]}
                                   onChange={this.handleGridChange.bind(this, 0, colIndex)}/>
                </td>
            )
        )}
</tr>


I’m sure there’s a way to use a nested .map() of the results of a .map() or some other clever approach to render the whole grid in a single go, but rendering each of the individual rows is an OK approach with me, since there are only nine rows. If the number of rows was much more than nine, then I’d spend some time working on a better approach, but I’m OK with this for now.

Flux Action and Store

The Action to call the Lambda, and maintaining the state of the responses in the Store was pretty simple. You can check out the source here if you’re interested.

CSS Styling for the Grid

One last thing to do was to style the grid so it looks like a usual Sudoku grid, with vertical and horizontal lines at 3 and 6, to divide the grid in 3×3 of the 3×3 squares. This took some reading to find out how to easily implement this, but it turns out that CSS nth-child() psuedoclass handles this perfectly. I covered this in this post here.

Take a Look at the App

I might move this to a more permanent home later, but if you want to check out the app, you can take a look here.

AWS AWS Lambda React (JavaScript library) Row (database) app

Published at DZone with permission of Kevin Hooke, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

Popular on DZone

  • Taming Cloud Costs With Infracost
  • Continuous Development: Building the Thing Right, to Build the Right Thing
  • Remote Debugging Dangers and Pitfalls
  • Event Driven 2.0

Comments

Partner Resources

X

ABOUT US

  • About DZone
  • Send feedback
  • Careers
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 600 Park Offices Drive
  • Suite 300
  • Durham, NC 27709
  • support@dzone.com
  • +1 (919) 678-0300

Let's be friends: