ben tedder : code things

Creating computed properties in React and Redux

A recent project I was working on had the requirement to show some calculated properties at the bottom of the page. I needed to show the following:

Summary

Subtotal: $3825.46
Profit: $994.62

Total: $4820.08

Those numbers were derived from a bunch of fields in a calculator above. Here's how it works. Create a selector, which is going to be treated as any other state property you map to your component. The selector accepts only the properties you want to listen to on the state, and returns a value.

Make sure you install reselect first:

npm install reselect --save

In my case I wanted to return several values, subtotal, profit and total.

// selectors/index.js
import { createSelector } from 'reselect'
import _ from 'lodash';

const profitMargin = (state) => state.calculator.profitMargin; const items = (state) => state.calculator.items;

export const getSummary = createSelector( [ profitMarginitems, ], (profitMargin, items) => { let subTotal = 0; let profit = 0; let total = 0; _.each(items, item => { subTotal += item.price; }); profit = profitMargin * subTotal; total = profit + subTotal;

return {
  subTotal,
  profit,
  total
}

} )

In the code above, the selector is listening to changes on any of the items, as well as changes on the profit margin. When it hears those, it runs my calculations and returns a value. Now let's use this in one of our container components:

// myContainer.js
import { getSummary } from '../selectors';

const mapStateToProps = (state, ownProps) => { return { otherState: state.otherState, summary: getSummary(state), } }

connect(mapStateToProps)(Calculator);

Once it's connected, we can inject it and use it like any other property:

// Calculator.js
const Calculator = ({ otherState, summary }) => (
  <div>
    <h1>Summary</h1>
    Subtotal: { summary.subTotal }<br/>
    Profit: { summary.profit }</br/>
    Total: { summary.total }</br/>
  </div>
)

That's pretty much it. No need to kick off extra actions or reducers to store any of those computed properties on state.