<div id="example"></div>
#example-component {
  position: relative;
}

#hot {
  position: absolute;
  top: 15px;
  left: 15px;
  width: 320px;
  height: 300px;
  overflow: hidden;
}

#action-list {
  position: absolute;
  top: 15px;
  left: 350px;
  
  h4 {
    margin: 0 0 0 15px;
    padding: 0;
  }
  
  .empty {
    color: #9e9e9e;
    margin: 15px 0 0 15px;
    font-style: italic;
    font-size: 17px;
  }
}

ul {
  margin: 0;
  padding: 0;
  max-width: 800px;
}

li.change {
  display: block;
  background: #d8f3d8;
  margin: 10px;
  padding: 10px;
}
View Compiled
const { createStore } = Redux;
const { combineReducers } = Redux;

const changes = (state = [], action) => {
  switch (action.type) {
    case 'change':
      return [
        ...state, {
          id: action.id,
          row: action.row,
          column: action.column,
          oldValue: action.oldValue,
          newValue: action.newValue,
          type: action.type
        }
      ]
    default:
      return state;
  }
}
const actionReducers = combineReducers({ changes });
const reduxStore = createStore(actionReducers);
class ActionList extends React.Component {
  constructor(props) {
    super(props);
  }
  
  render() {
    let result = null;

    if (this.props.actionList.length === 0) {
      result = <div className="empty">
          Empty. Make some changes to the table on the left!
        </div>

    } else {
      result = this.props.actionList.map(function(action) {
        return <li key={action.id} className={action.type}>Value changed at <i>({action.row}, {action.column}) </i> 
          from <strong>"{action.oldValue}"</strong> to <strong>"{action.newValue}"</strong></li>
      })
    }
    return (
      <div id="action-list">
        <h4>Change log:</h4>
        <ul>
          {result}
        </ul>
      </div>
    );
  }
}

class ExampleComponent extends React.Component {
  constructor(props) {
    super(props);
    this.handsontableData = [
      ["", "Ford", "Volvo", "Toyota", "Honda"],
      ["2016", 10, 11, 12, 13],
      ["2017", 20, 11, 14, 13],
      ["2018", 30, 15, 12, 13]
    ];
  }

  render() {
    return (
      <div id="example-component">
        <HotTable root="hot" settings={{
            data: this.handsontableData,
            colHeaders: true,
            rowHeaders: true, 
            onAfterChange: (changes, source) => {
              if (source !== 'loadData') {
                reduxStore.dispatch({
                  id: reduxStore.getState().changes.length,
                  type: 'change',
                  row: changes[0][0],
                  column: changes[0][1],
                  oldValue: changes[0][2],
                  newValue: changes[0][3]
                });                  
              }
            }
          }}/>
        <ActionList actionList={reduxStore.getState().changes}/>
      </div>
    );
  }
}

const render = () => {
  ReactDOM.render(<ExampleComponent />, document.getElementById('example'));
}
reduxStore.subscribe(render);
render();
View Compiled
Run Pen

External CSS

  1. https://docs.handsontable.com/bower_components/handsontable/dist/handsontable.full.min.css
  2. https://cdnjs.cloudflare.com/ajax/libs/pikaday/1.5.1/css/pikaday.min.css

External JavaScript

  1. https://cdnjs.cloudflare.com/ajax/libs/react/15.3.1/react.js
  2. https://cdnjs.cloudflare.com/ajax/libs/react/15.3.1/react-dom.js
  3. https://docs.handsontable.com/bower_components/handsontable/dist/handsontable.full.min.js
  4. https://unpkg.com/react-handsontable/dist/react-handsontable.min.js
  5. https://cdnjs.cloudflare.com/ajax/libs/redux/3.6.0/redux.min.js