Updating my React Sudoku Solver app: Replacing Flux with Redux (part 1)

A while back I built a React frontend for a AWS Lambda Sudoku solver. At the time I used Flux (original source for this app is here), but I’m taking a look at updating it to replace Flux with Redux.

As a starting point I took another example React app, a simplest case app using Flux and then converted it to Redux. After working through the changes to update this app to use Redux, I put together a quick cheatsheet of changes here. Here’s both projects for a comparison:

https://github.com/kevinhooke/SimpleReactFluxExample

https://github.com/kevinhooke/SimpleReactReduxExample

Here’s a walkthrough of the main changes to an existing app (summarizing the steps from my cheatsheet, link above, and looking at some of the steps in more detail):

  • install react-redux and react-devtools-extension
  • create a store using Redux createStore, replacing previous Flux store that used Dispatcher, EmitEvent and [add|remove]ChangeListeners
  • create reducers to manipulate the Store
  • wrap root component with <Provider>
  • connect components with the Store

The Redux approach to maintaining state in the Store is significantly different from Flux:

  • Redux has a single store, whereas Flux can have many
  • State maintained in a Redux Store is manipulated with reducer functions
  • Reducer functions take the state to be manipulated and actions that are applied to the state to change it
  • Flux maintains a copy of the state in variables in the Store itself, whereas the current state of the store is passed as an argument to reducers, and a new updated copy is returned as the result

Since there’s a number of changes to the store, it’s worth looking at each of these in more detail.

Updating Flux Store to a Redux Store

Previously my Flux store maintained state in two vars:

var puzzleData = {}
var message = {}

These are no longer needed in the Redux store, but there in an initialState for initializing the Store. This can simply be the same as puzzleData before but just renamed for clarity:

const initialPuzzleData = {}

Next, each of the case statements in the Action can move over to the reducer function, and updated to manipulate the content of the store passed as a param and then return the modified store as the result. For example, previously each action was handled like this:

case 'NEW_DATA' :
  this.setData(action.data);
  this.emit('change');
  break;

With Redux, each case block is now going to look more like this:

case 'NEW_DATA' :
  return Object.assign( {}, action.data );

Create ActionCreators

In Flux, an Action combines a couple of concepts, it’s the payload to be dispatched to the Store as well as the mechanism for performing the dispatch of the Action. With Redux these concepts are separate, and the Action is merely the payload to apply to updating the Store. There is a concept of Action Creators though, that can be called to build the Action payload. Before with Flux we would have an Action function like this:

    initSamplePuzzle(){
        console.log("SudokuSolverAction initSamplePuzzle()");
        var puzzle = {
            rows:
                [
                    ["", "", "", "8", "1", "", "6", "7", ""],
                    ["", "", "7", "4", "9", "", "2", "", "8"],
                    ["", "6", "", "", "5", "", "1", "", "4"],
                    ["1", "", "", "", "", "3", "9", "", ""],
                    ["4", "", "", "", "8", "", "", "", "7"],
                    ["", "", "6", "9", "", "", "", "", "3"],
                    ["9", "", "2", "", "3", "", "", "6", ""],
                    ["6", "", "1", "", "7", "4", "3", "", ""],
                    ["", "3", "4", "", "6", "9", "", "", ""]
                ]
        }

        AppDispatcher.dispatch({
            actionName: 'NEW_DATA',
            data: puzzle.rows
        });
    }

and now this is simplified to build the payload, the Flux Dispatcher is removed, and the function. now just returns the payload to be processed:

    return {
        actionName: 'NEW_DATA',
        data: puzzle.rows
    };

Another simple example that builds an Action object for an update to the Store:

export function updateGrid(payload) {
    return { type: NEW_DATA, payload }
};

Connecting Components to the Store

In each Component, implement mapStateToProps and mapDispatchToProps to pass store and dispatch() as props to each Component, and call connect() to connect each Component with your Redux Store.

Here’s my matchStateToProps:

const mapStateToProps = state => {
    return { 
        grid: state.grid,
        message: state.message
     };
};

And here’s my mapDispatchToProps:

function mapDispatchToProps(dispatch) {
    return {
        updatePuzzleData :  grid => dispatch(updatePuzzleData(grid)),
        clearData : () => dispatch(clearData()),
        initSamplePuzzle : () => dispatch(initSamplePuzzle())
    }
}

mapDispatchToProps is where your Action Creators are called to create Action objects for modifying state, and then dispatched to apply against the state of the Store by your reducers.

Connect your components to your Store with a call to connect() :

const SudokuSolver = connect(mapStateToProps, mapDispatchToProps)(ConnectedSudokuSolver);

export default SudokuSolver;

Part 2

In part 2 I’ll look at moving the api call from the Flux Action to use Redux middleware and thunks.

What happened to the proliferation of Java web frameworks from the early 2000s?

Back in the early 2000s if you were a Java developer working on building web apps, chances are you were using Apache Struts. It was the de facto, go-to web framework of it’s time, pretty much used everywhere by everyone (it was even noticeable online for it’s pattern of using ‘*.do’ URLs for its Actions). However, it wasn’t the only framework in town. Around early to mid 2000s there was an explosion of Java based web frameworks being developed, for a while it seems like it was the-thing-to-do to build your own web framework because after all, you know better than all the other guys right?

Joking aside, other major frameworks that appeared, some of the other big names were Wicket, Cocoon, Tapestry, Webwork (Webwork and Struts merged to form Struts 2), GWT and Vaadin. In the Java EE space the standard web framework became JSF but never really gained traction over any of the others. The one that stayed the course and probably the only one still in serious usage would be Spring Web MVC.

The funny thing about all this churn that occurred is that it feels like it’s all happening again, but now in the Javascript space. Sure, once we realized we could could offload some of this backend rendering of the UI to the frontend and after Google had shown the way with GMail showing us how the user experience of a single page app is far better than the traditional request/response of web apps we had become used to, it was inevitable that serverside based Java web frameworks would fall out of favor and get replaced by Javascript clientside frameworks. Was it inevitable that the industry would go through the same learning pains once again though? I’m not sure, but it happened.

At one point jQuery was the de facto JavaScript framework, much like Struts was in the Java space back in it’s time. Then came the flood: backbone, ember, Dojo, Knockout seemed to to be the main players, eventually settling down to ‘the big 3’ that we have today, Angular, React and Vue.

So what happened to all the Java web frameworks? Spring Web MVC is still around and still in use. With the change in technologies and a shift in focus from backend web frameworks to frontend, the backend web frameworks became less relevant. Could this shift happen again? Sure, when the next big things comes along.

Moral of the story: tech changes quick in software development. Keep an eye out for whats coming next, because what’s hot today can quickly become irrelevant tomorrow.

Additional reading: if you’re interested to read more about Java web frameworks, Zeroturnaround’s Rebel Labs used to do a survey on framework usage, and you can see their findings from their relatively recent reports, from 2014, 2015 and 2017:

https://www.jrebel.com/blog/java-tools-and-technologies-landscape-2014#Web%20Frameworks

https://www.jrebel.com/blog/java-web-framework-usage-stats

https://www.jrebel.com/blog/java-web-frameworks-index