3
votes

I have an app which logs income, expenditure and transactions. Each has their own respective component, and within that component, I want to list all of the financial data, so in the transactions, list each transaction for a calendar month and it’s details, value etc.

on the dashboard, I want to render: the total value for all transactions, expenditure, and income. Then available to spend, by subtracting expenditure and transactions from income.

The financial data is from Redux store, then on the dashboard component, I have initialised state for the totals:

constructor(props) {
    super(props);

    this.state = {
        expenditureTotal: 0,
        incomeTotal: 0,
        transactionsTotal: 0
    }
}

I have a sumTotal method which I pass each chunk of data to calculate the totals:

sumTotal(data) {

    return data
        .map((obj) => { return obj.amount; })
        .reduce((prev, next) => { return prev += next; }, 0);

}

I need to update the component state with these totals so I can then calculate and display the remaining balance, but I am not sure of the appropriate way to update the state values, as the relevant values are only calculated on render via the sumTotal method. How to I then setState with the new totals, to then pass down to the Remaining Balance component (which I need to create).

Below is the relevant parts of the component, any help would be amazing. Thank you.

class Transactions extends Component {

    constructor(props) {
        … as code sample above
    }

    componentWillMount() {
        fetch data from redux

    }

    sumTotal(data) {
        … as code sample above
    }

    render() {
        const { transactions, expenditure, income } = this.props;
        const { transactionsTotal, expenditureTotal, incomeTotal } = this.state;

        if (!transactions || !expenditure || !income) {
            return (
                    <div>
                        <p>Loading...</p>
                    </div>
            )
        }

        return (
            <section>
                <h2>Transactions <Link className="actionlink" to="/transactions/add">Add</Link></h2>
                <table className="financials -transactions">
                    <thead>
                        <tr>
                            <th>Name</th>
                            <th>Date</th>
                            <th className="activefilter">Amount</th>
                            <th className="actions">&nbsp;</th>
                            <th className="actions">&nbsp;</th>
                        </tr>
                    </thead>
                    <tbody>
                    {this.props.transactions.map(
                        (transaction, i) =>
                            <Transaction {...this.props} key={i} transaction={transaction} delete={this.handleDelete} />
                    )}
                    </tbody>
                </table>

                <section className="sumtotal">
                    <Total value={this.sumTotal(transactions)} type="Transactions" />
                    <Total value={this.sumTotal(expenditure)} type="Expenditure" />
                    <Total value={this.sumTotal(income)} type="Income" />

                    <div className="remaining">
                        Display state totals calculation here
                    </div>

                </section>
            </section>
         );
    }
}

function mapStateToProps(state) {
    return {
        transactions: state.transactions.all,
        expenditure: state.expenditure.all,
        income: state.income.all
    };
}

function mapDispatchToProps(dispatch) {
    return bindActionCreators(actionCreators, dispatch);
}

export default connect(mapStateToProps, mapDispatchToProps)(Transactions);
1
after you dispatch the action, you will receive new state in mapStateToProps. Then write a componentWillReceiveProps in your component. Inside that, update the state based on new propsDeadfish
Pass the sumTotals as props to the Balance component.vijayst

1 Answers

2
votes

By adding the total to the states you are introducing redundancy and risk of inconsistence to your model. It is better to have a single source of truth and derivate the totals from them. To avoid to have to recalculate them all the time, if performance is a concern, you can use memoized selectors.

Have a look to this page where they add memoized selectors in redux using reselect.