Interrelated personal side projects can be a goldmine of learning opportunities

Some people struggle to find ideas for working on side/personal software development projects for learning (and fun!). I’ve kept a running list of ideas in an online notebook and if I’m struggling for an idea for a new project I refer back to this list.

Over the past couple of years I stumbled across a series of inter-related projects that’s been a goldmine of learning opportunities, from frontend to backend to serverless.

This series of projects started with a question “Can you solve a problem without understanding the problem?”. tl;dr? No. The problem for this activity was solving Sudoku puzzles, and you can read more about this here:

This lead to the next step, researching more about exact cover problems, and how they can be solved with well established algorithms:

After building an implementation of Donald Knuth’s Algorithm X, I packaged it up as an AWS Lambda, and then built a React frontend for it:

I have one other project in progress for the frontend, replacing Flux with Redux. I’m still working on that one.

After building my solver and the frontend, I starting thinking about how to generate new puzzles. This is in progress here: https://github.com/kevinhooke/sudoku-generator

If you’re generating new puzzles you also need a way to grade the difficulty of puzzles. The unusual thing about this is there’s no established algorithm for grading the complexity of Sudoku puzzles, they’re typically graded by applying human solving techniques, so this led to this: https://github.com/kevinhooke/sudoku-human-grader

This string of related projects has kept me busy of the past couple of years. Not every idea will lead to a series of related projects like this, but if you can find an idea that does, it will keep you busy with plenty of problems to solve and many learning opportunities.

React Redux cheatsheet

This is my summary of the bare minimum steps as a quick-ref cheatsheet for adding Redux to an existing React app. This is just some notes for future reference. If you’re looking for tutorials, take a look at:

Here’s my quickref:

npm i react-redux

Add Redux devtools for Chrome (see here):

npm install --save redux-devtools-extension

Wrap <Provider> around root Component to share the Store with all child components:

import { Provider } from 'react-redux'
import store from './store'

<Provider store={store}>
  <App>
</Provider>

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:

const mapStateToProps = (state) => {
  return {
    yourcomponent: state.yourcomponent
  }
}
export default connect(
  mapStateToProps,
  mapDispatchToProps
)(YourComponent)

Create a Store:

import { createStore } from 'redux';
import { devToolsEnhancer } from 'redux-devtools-extension';
let store = createStore(yourReducer, devToolsEnhancer());
export default store;

Create reducers for Store – here’s an example that take the the value of a label from the passed action payload and sets it in the Store – remember the state of the store is always treated as immutable, so always create a new copy of the modified state, here using Object.assign():

function labelReducer(state = initialState, action) {
  switch (action.type) {
    case 'CHANGE_LABEL':
      return Object.assign( {},{ labelValue : action.payload 
    } );
    default:
      return state;
    }
}

Implement an action creator that builds an Action object that requests changes to the Store – each action has a type and a payload:

export function changeLabel(payload) {
  return { type: "LABLE_CHANGE", payload }
};

Implement mapDispatchToProps – you can either build the Action object yourself here, or call an Action creator like the above example:

function mapDispatchToProps(dispatch) {
return {
  changeLabel: labelValue => 
    dispatch(changeLabel(labelValue))
  };
}

Pass mapDispatchToProps to your connect() call shown earlier.

As a comparison, here’s a simple React app using Flux:

https://github.com/kevinhooke/SimpleReactFluxExample

… and here’s the same app converted to use Redux:

https://github.com/kevinhooke/SimpleReactReduxExample

Done!

React and Redux error: “_react.default.createContext is not a function”

I’m adding Redux to an existing React app, converting from Flux to Redux. After wrapping my root component with the <Provider> I got this error and the app doesn’t initialize:

_react.default.createContext is not a function

Doing a quick search found this post suggesting I’ve got a mismatch in versions between newest Redux versions and possibly older versions of React. This is possible as I’m updating an older React app I put together a couple of years ago. Quick way to test this, remove React and react-dom and add them back again.

Right now I have:

"react": "^15.4.1",
"react-dedux": "^0.4.0-beta.4",
"react-dom": "^15.4.1",
"react-redux": "^7.2.0"

Removed React and react-dom and added back latest versions:

"react": "^16.13.1",
"react-dedux": "^0.4.0-beta.4",
"react-dom": "^16.13.1",
"react-redux": "^7.2.0"

Restated my app, fixed!

node.js, node-oracledb and Oracle Instant Client

To access an Oracle DB from an AWS Lambda function developed with node.js, you need to package you Lambda with shared libraries from Oracle’s Instant Client. The install instructions are here ( http://oracle.github.io/node-oracledb/INSTALL.html#quickstart ) but the only part that is really needed is the download location (since there’s no specific instructions for bundling the libs with an AWS Lambda): https://www.oracle.com/database/technologies/instant-client/linux-x86-64-downloads.html

Not all the Oracle Instant Client files are needed. From this older npm module to automate the packaging of the required libraries, I used this same list of required libraries:

libclntshcore.so.19.1
libclntsh.so.19.1
libmql1.so
libipc1.so
libnnz19.so
libons.so (not packaged in current Instant Client)
libociicus.so
libaio.so (from separate download - see next step)

libaio – if you’re on a Linux platform you can ‘apt-get install libaio’ or similar, but building my Lambda on a Mac I had to manually download the package and extract just the .so file from here (download the Arch Linux x64 package): https://pkgs.org/download/libaio

Put these in a /lib dir and zip up the folder and files. Use this to create a Lambda Layer.

For the Lambda itself install the node.js module for the api:

npm install –save node-oracledb

For examples in api usage, see the examples here: https://github.com/oracle/node-oracledb/tree/master/examples