where to insert my todo in reactJs using axios post request? - reactjs

where to write axios post request to insert todo into database.If I write axios post request in componentDidUpdate() whenever click on checkbox for todo_completed status it will insert in database. duplicate record maintains fro true and false. i dont understand where to call post request in todoApp.jsx
Here is my Code
todoapp.jsx
var React = require('react');
var TodoSearch = require('TodoSearch');
var AddTodo = require('AddTodo');
var TodoList = require('TodoList');
var axios= require('axios');
var TodoApp=React.createClass({
getInitialState:function(){
return{
todo_completed:false,
strSearchText:'',
todos:[]
};
},
componentDidMount:function(){
var that=this;
axios.post('/displaytodo').then(function (response){
console.log("display");
var todos=response.data;
console.log(todos);
that.setState({
todos:response.data
});
}).catch(function (error){
console.log(error);
});
},
componentDidUpdate:function(){
var todo_text="";
var todo_completed="";
this.state.todos.forEach(function(todo){
todo_text= todo.todo_text;
todo_completed=todo.todo_completed;
});
//insert todo in database
axios.post('/addtodo',{
todo_text:todo_text,
todo_completed:todo_completed
}).then(function (response) {
console.log("data");
}).catch(function (error) {
console.log(error);
});
},
handleAddTodo:function(todo_text){
alert("new todo "+todo_text);
//insert query needed to add todo
this.setState({
todos:[
...this.state.todos,
{
todo_text:todo_text,
todo_completed:false
}
]
});
},
handleToggle:function(todo_id){
var updatedTodos=this.state.todos.map((todo)=>{
if(todo.todo_id===todo_id){
todo.todo_completed=!todo.todo_completed;
}
return todo;
});
//update query required for completed status
this.setState({
todos:updatedTodos
})
//alert(id);
},
handleSearch:function(boolShowCompleted,strSearchText){
this.setState({
boolShowCompleted:boolShowCompleted,
strSearchText:strSearchText.toLowerCase()
});
},
render:function(){
var urlValue = this.props.params.sessionValue;
console.log(urlValue);
var {todos}=this.state;
return(
<div>
{urlValue}
<TodoSearch onSearch={this.handleSearch}/>
<TodoList todos={todos} onToggle={this.handleToggle}/>
<AddTodo onAddTodo={this.handleAddTodo}/>
</div>
)
}
});
module.exports=TodoApp;
AddTodo.jsx
var AddTodo = React.createClass({
handleSubmit: function(e) {
e.preventDefault();
var strTodoText = this.refs.strTodoText.value;
if (strTodoText.length > 0) {
this.refs.strTodoText.value = '';
this.props.onAddTodo(strTodoText);
} else {
this.refs.strTodoText.focus();
}
},
render: function() {
return ( < div >
< form onSubmit = { this.handleSubmit } >
< input type = "text" ref = "strTodoText" / >
< button className = "button" > Add Todo < /button>
</form > Add todo.....
< /div>
)
}
});

You need to add an axios post request at two places,
In the handleAddTodo function, that gets called when the new todo is added. With this post request you need to insert a new entry into the table
In the handleToggle function, that gets called when you toggle the state of todo, With this post request you need to update the entry that already exist in your table

Related

Showing a loading message until the blob file is downloaded

I am printing a bill as a pdf document after submitting the billing form. The service that is downloading the blob file is as follows.
export default [createLogic({
type: reportTypes.REPORT,
latest: true,
debounce: 2000,
process({ MockHTTPClient, getState, action }, dispatch, done) {
dispatch(reportActions.queryStart())
let HTTPClient;
if (MockHTTPClient) {
HTTPClient = MockHTTPClient;
} else {
HTTPClient = API;
}
HTTPClient.Post(endPoints.REPORTS_BILL, action.payload.reportOptions)
.then(
(resp) => {
return resp.data
})
.then((data) => {
dispatch(reportActions.getReportSuccess(data));
var link = document.createElement('a');
link.href = `data:application/octet-stream;base64,${data}`;
var today = new Date();
var date = today.getFullYear() + '-' + (today.getMonth() + 1) + '-' + today.getDate();
var time = today.getHours() + ":" + today.getMinutes() + ":" + today.getSeconds() + ":" + today.getMilliseconds();
var dateTime = date + ' ' + time;
var fileName = dateTime + "billing.pdf";
link.download = fileName;
link.click();
var base64str = data;
var binary = atob(base64str.replace(/\s/g, ''));
var len = binary.length;
var buffer = new ArrayBuffer(len);
var view = new Uint8Array(buffer);
for (var i = 0; i < len; i++) {
view[i] = binary.charCodeAt(i);
}
var blob = new Blob([view], { type: "application/pdf" });
var url = URL.createObjectURL(blob);
window.open(url);
dispatch(reportActions.getReportSuccess(data))
})
.then(() => dispatch(reportActions.queryEnd()))
.catch(err => {
dispatch(reportActions.getReportFailed());
var errorMessage = "Failed to get prductivity data.";
if (err && err.code == "ECONNABORTED") {
errorMessage = "Please check your internet connection.";
}
dispatch(
reportActions.getReportFailed({
title: "Error!",
message: errorMessage
})
);
})
.then(() => done());
}
})
]
In the Billing Component following is the method that I am calling the service.
printBill = () => {
debugger;
var reportType = 1;
var reportFiltersSet = {};
if (this.billingOptions.length > 0) {
this.billingOptions.map(v => {
reportFiltersSet[v.name] = v.value;
});
}
this.props.reportActions.queryStart();
var reportType = 1; //Thiis need to be dynamic. use this => //this.state.reportType
var reportFilters = this.state.billingOptions;
if (
reportFiltersSet.organization == undefined ||
reportFiltersSet.department == undefined ||
reportFiltersSet.division == undefined ||
reportFiltersSet.billYear == undefined ||
reportFiltersSet.billMonth == undefined
) {
this.setState({
reportContentNull: true,
warning: "Error!",
errorMessage:
"Either department or division reqiured with organization , year and month",
negative: true,
hidden: false
});
this.props.reportActions.getReport({ reportOptions: reportFiltersSet });
var reportDownloadType = this.state.reportType;
};
I can download the blob file , when I submit the form without any problem. But in user's perspective it is important to show that the loading state in order to have a better user experince. Therefore can anyone help me out to show a loading message during the submit and loading the blob file?
So the Idea is to start loading as soon as HTTP calls happens and remove it when response is recieved.
Simple way would be add a loading variable in state and in render check that variable and show spinner.
onClick = () => {
this.setState({ loading: true }, () => {
Axios.get('/sampelCall')
.then(result => this.setState({
loading: false,
data: [...result.data],
}));
});
}
render() {
const { data, loading } = this.state;
return (
<div>
<button onClick={this.onClick}>
Load Data
</button>
{loading ? <LoadingSpinner /> : <ResultsTable results={data} />} // if loading in true will show Spinner
</div>
);
}
Note:
You need to handle loading variable in all cases (Success/Error) else Spinner will keep on loading.

React component props not updating

Hello Im creating a simple React Component with just a label that change its content when a SignalR method is fired. My react component is like this one:
var PersonalityStatusApp = React.createClass({
getInitialState: function () {
return { data: dataInit };
},
componentWillMount(){
var self = this;
this.setState({ data:this.props.status});
Votinghub.on("UpdateStatusLabel", function (data) {
var obj = $.parseJSON(data);
self.setState({ data: obj });
});
},
render: function () {
return (
<div className="PersonalityStatusApp">
<label>{this.props.status}</label>
</div>
);
}
});
When te component receives a UpdateStatusLabel signalR message it change the State of the component with the value that gets from the signalR message.
The method UpdateStatusLabel gets the correct value.
This fires the render method, but when I check the properties in the render method I see thnat the values are still the ones from the initial state.
Can somebody help me?
Reason is, you are updating the state variable and printing the props value. Initially state variable data will have the value of this.props and after you get the signalR you are updating the state by data: obj, so print the value of this.stat.data.status it will print the updated value.
use this:
return (
<div className="PersonalityStatusApp">
<label>{this.state.data.status}</label>
</div>
);
Note: Initially you need to set the value of data: this.props
Full part:
var PersonalityStatusApp = React.createClass({
getInitialState: function () {
return { data: dataInit };
},
componentWillMount(){
var self = this;
this.setState({ data: this.props}); //changed this
Votinghub.on("UpdateStatusLabel", function (data) {
var obj = $.parseJSON(data);
self.setState({ data: obj });
});
},
render: function () {
return (
<div className="PersonalityStatusApp">
<label>{this.state.data.status}</label>
</div>
);
}
});

React -render values onClick of tabs

I have an app that uses axios and that render the values (eg: ID and warehouseName) using map which i put on tabs. Now I want to do is post a state on warehouseID at loadBrandTotal() from the value ID that I get in the map.
So far my code is like this
export default React.createClass({
getInitialState(){
return {
warehouseName: ""
}
},
componentWillMount(){
this.loadWarehouse();
this.loadBrandTotal();
},
loadWarehouse(){
var that = this
var url = api + 'retrieveWarehouseList';
axios.post(url,
{
warehouseName : 'NONE'
})
.then(function (response) {
console.log(response.data);
that.setState({
warehouseList : response.data.retrieveWarehouseListResult
});
})
.catch(function (response) {
console.log(response);
});
},
loadBrandTotal(){
var that = this
var url = api + 'retrieveTotalSalesPerBrand';
axios.post(url,
{
warehouseID : "None"
})
.then(function (response) {
console.log(response.data);
that.setState({
totsalesperbrand : response.data.retrieveTotalSalesPerBrandResult
});
})
.catch(function (response) {
console.log(response);
});
},
render() {
var wareName = this.state.warehouseList;
return (
<ul className="tabs tabs-transparent">
{wareName.map(function(nameoObjects) {
return (
<li className="tab">
<a href="#test1" value={nameoObjects.ID} key={nameoObjects.ID}>{nameoObjects.warehouseName}</a>
</li>
)
})}
</ul>
)}
})
Thanks a lot in advance.
I'm not 100% sure what you're wanting to do, but is it that inside the loadBrandTotal() function you want to post data you've gotten in the loadWarehouse() function? And if so, WHEN are you wanting to do this posting, as it's rendered? On a button click?
Here's an example where each list element has a button that sends the ID value the element got in the map fucntion to the loadBrandTotal() function, where it's posted (see code comments for changes):
// Give the id as an argument to loadBrandTotal
loadBrandTotal(id){
var that = this
var url = api + 'retrieveTotalSalesPerBrand';
axios.post(url,
{
// Post the ID
warehouseID : id
})
.then(function (response) {
console.log(response.data);
that.setState({
totsalesperbrand : response.data.retrieveTotalSalesPerBrandResult
});
})
.catch(function (response) {
console.log(response);
});
},
render() {
var wareName = this.state.warehouseList;
return (
<ul className="tabs tabs-transparent">
{wareName.map(function(nameoObjects) {
return (
<li className="tab">
<a href="#test1" value={nameoObjects.ID} key={nameoObjects.ID}>{nameoObjects.warehouseName}</a>
// When clicked, this button sends THIS list object's nameoObject ID to the loadBrandTotal function, where it's posted
<button onClick{() => this.loadBrandTotal(nameoObjects.ID)}>Post ID</button>
</li>
)
})}
</ul>
)}
So in that example, every list element rendered in the map function includes a button that, when clicked, sends its own nameoObject ID to the loadBrandTotal function, where it's posted and the state is set. Is that the kind of thing you're trying to do?

enzyme shallow calls imported function when passed wrong parameters

I have a component that I am writing automated tests for. I want to test a method of this component. THe purpose if this test if if the method will call an imported function when passed the wrong parameters.
This is my component (I removed the non-relevant code):
//Util
import { getMenu } from '../utils/request';
const Dashboard = React.createClass({
getInitialState() {
let today = new Date();
if (today.getDay() == 6) {
today.setDate(today.getDate() + 2);
} else if (today.getDay() == 0) {
today.setDate(today.getDate() + 1);
}
return {
selectedDate: today.toISOString().substring(0, 10)
}
},
componentDidMount() {
getMenu(this.state.selectedDate, (data) => {
if (data.error) {
this.setState({
error: data.error
})
} else {
this.setState({
dailyMenu: data.dailyMenu,
loading: false
})
}
})
},
handleDateChange(date) {
var newDate = date.toISOString().substring(0, 10);
if(newDate !== this.state.selectedDate) {
getMenu(newDate, (data) => {
if (data.error) {
this.setState({
error: data.error
})
} else {
this.setState({
dailyMenu: data.dailyMenu,
loading: false,
selectedDate: newDate
})
}
})
}
},
render() {
return (
<MuiThemeProvider>
<div className="Dashboard">
<div className="Dashboard-body">
<Sidebar dateClick={this.handleDateChange}/>
</div>
</div>
</MuiThemeProvider>
)
}
});
module.exports = Dashboard;
I am mocking the getMenu function using jest.mock:
// Components
import Dashboard from '../components/Dashboard';
// Utils
import { getMenu } from '../utils/request';
jest.mock('../utils/request', () => ({getMenu: jest.fn()}))
Then I have written two tests. The first one passes different dates, the second one passes the same date. So in the second case the getMenu mock should not get called. But for both tests I get the result that the function was called one time:
it('handleDateChange should call getMenu when NOT passed state date', ()=> {
const dashboard = shallow(<Dashboard/>);
const today = new Date();
const longAgo = new Date(1).toISOString().substring(0, 10);
dashboard.setState({ selectedDate: longAgo });
dashboard.instance().handleDateChange(today);
expect(getMenu).toHaveBeenCalledTimes(1);
});
it('handleDateChange should NOT call getMenu when passed state date', ()=> {
const dashboard = shallow(<Dashboard/>);
const today = new Date();
const selectedDate = today.toISOString().substring(0, 10);
dashboard.setState({ selectedDate: selectedDate });
dashboard.instance().handleDateChange(today);
expect(getMenu).toHaveBeenCalledTimes(0);
});
So I did some console logs and so far everything seems as expected:
console.log(today.toISOString().substring(0, 10));
console.log(dashboard.state('selectedDate'));
console.log(today.toISOString().substring(0, 10) !== selectedDate);
This outputs:
2017-01-12
2017-01-12
false
What am I doing wrong?

Passing an identifier to a module in React

Apologies, I probably have all of my terminology wrong here, but I am chunking up a React app into modules and am trying to combine two modules which do the same thing and come into an issue.
Specifically, I am trying to sum up totals of both income and expenditure, and have been calling two different react classes via:
<ExpenditureTotal type={this.state.cashbook.expenditure} addTotal={this.addTotal} /> and another <IncomeTotal... which does the same).
The Class is as follows (expenditure shown, but income is the same:
/* Expenditure Running Total */
var ExpenditureTotal = React.createClass({
render: function() {
var expIds = Object.keys(this.props.expenditure);
var total = expIds.reduce((prevTotal, key) => {
var expenditure = this.props.expenditure[key];
return prevTotal + (parseFloat(expenditure.amount));
}, 0);
this.props.addTotal('expenditure', total);
return(
<h2 className="total">Total: {h.formatPrice(total)}</h2>
);
}
});
I wanted to combine the two by making it more generic, so I made the following:
/* Cashflow Running Total */
var TotalCashflow = React.createClass({
render: function() {
var expIds = Object.keys(this.props.type);
var total = expIds.reduce((prevTotal, key) => {
var type = this.props.type[key];
return prevTotal + (parseFloat(type.amount));
}, 0);
this.props.addTotal('type', total);
return(
<h2 className="total">Total: {h.formatPrice(total)}</h2>
);
}
});
The only reason it doesn't work properly is when I add the summed total to the relevant state object which for this is income or expenditure in totals: (totals: { income: val, expenditure: val}).
Where I was previously explicitly specifying 'expenditure' or 'income' in the module, (seen above in ExpenditureTotal as this.props.addTotal('expenditure', total);, I am not sure in React how to pass the total value to the relevant place - it needs to read either 'expenditure' or 'income' to populate the correct state totals key.
Apologies if this is a bit garbled, struggling to explain it clearly.
Thank you :)
Update: App component in full:
import React from 'react';
// Firebase
import Rebase from 're-base';
var base = Rebase.createClass("FBURL")
import h from '../helpers';
import Expenditure from './Expenditure';
import Income from './Income';
import TotalCashflow from './TotalCashflow';
import AddForm from './AddForm';
import Available from './Available';
var App = React.createClass({
// Part of React lifecycle
getInitialState: function() {
return {
cashbook: {
expenditure: {},
income: {}
},
totals: {},
available: {}
}
},
componentDidMount: function() {
// Two way data binding
base.syncState('cashbook', {
context: this,
state: 'cashbook'
});
},
addExpenditure: function(expenditure) {
var timestamp = (new Date()).getTime();
// update state object
this.state.cashbook.expenditure['expenditure-' + timestamp] = expenditure;
// set state
this.setState({
cashbook: { expenditure: this.state.cashbook.expenditure }
});
},
addIncome: function(income) {
var timestamp = (new Date()).getTime();
// update state object
this.state.cashbook.income['income-' + timestamp] = income;
// set state
this.setState({
cashbook: { income: this.state.cashbook.income }
});
},
removeExpenditure: function(key) {
this.state.cashbook.expenditure[key] = null;
this.setState({
cashbook: { expenditure: this.state.cashbook.expenditure }
});
},
renderExpenditure: function(key) {
var details = this.state.cashbook.expenditure[key];
return(
<tr className="item" key={key}>
<td><strong>{details.name}</strong></td>
<td><strong>{h.formatPrice(details.amount)}</strong></td>
<td>{details.category}</td>
<td>{details.type}</td>
<td>{details.date}</td>
<td><button className="remove-item" onClick={this.removeExpenditure.bind(null, key)}>Remove</button></td>
</tr>
);
},
removeIncome: function(key) {
this.state.cashbook.income[key] = null;
this.setState({
cashbook: { income: this.state.cashbook.income }
});
},
renderIncome: function(key) {
var details = this.state.cashbook.income[key];
return(
<tr className="item" key={key}>
<td><strong>{details.name}</strong></td>
<td><strong>{h.formatPrice(details.amount)}</strong></td>
<td>{details.category}</td>
<td>{details.type}</td>
<td>{details.date}</td>
<td><button className="remove-item" onClick={this.removeIncome.bind(null, key)}>Remove</button></td>
</tr>
);
},
listInventory: function() {
return
},
addTotal: function(type, total) {
this.state.totals[type] = total;
},
render: function() {
return(
<div className="cashbook">
<Expenditure
cashbook={this.state.cashbook.expenditure}
renderExpenditure={this.renderExpenditure} />
<TotalCashflow
type={this.state.cashbook.expenditure}
addTotal={this.addTotal}
identifier='expenditure'
/>
<AddForm addCashflow={this.addExpenditure} />
<Income
cashbook={this.state.cashbook.income}
renderIncome={this.renderIncome} />
<TotalCashflow
type={this.state.cashbook.income}
addTotal={this.addTotal}
identifier='income'
/>
<AddForm addCashflow={this.addIncome} />
<Available totals={this.state.totals} />
</div>
);
}
});
export default App;
If I got you correctly, you want to have a component, that renders the totals of 'expenditure' and/or 'income'. Notice, you should not modify the state within the render function, as these will trigger over and over again, with each state change it is invoking itself.
Instead, try to compute the necessary data from within the parent components componentDidMount/componentDidUpdate, so that the TotalCashflow can be served the data, without it needing to do any more logic on it.
This might be the parent component:
/* Cashflow-Wrapper */
var TotalCashflowWrapper = React.createClass({
componentDidMount: function(){
this.setState({
income: this.addTotal(/*x1*/)
expenditure: this.addTotal(/*x1*/)
});
/*x1: hand over the relevant 'type' data that you use in the child components in your example*/
}
addTotal: function(type) {
var expIds = Object.keys(type);
return expIds.reduce((prevTotal, key) => {
var x = type[key];
return prevTotal + (parseFloat(x.amount));
}, 0);
}
render: function() {
return(
<div>
<TotalCashflow total={this.state.expenditure}/>
<TotalCashflow total={this.state.income}/>
</div>
);
}
});
This would be your total component:
/* Cashflow Running Total */
var TotalCashflow = React.createClass({
render: function() {
return(
<h2 className="total">Total: {h.formatPrice(this.props.total)}</h2>
);
}
});
Edit
There are a few issues with your App component, but first of all, here is how you could redesign/simplify it. You should also move the markup from renderExpenditure and renderIncome to your Income/Expenditure components. I've been using ES6, as I've noticed you're already using arrow functions.
var App = React.createClass({
getInitialState: function () {
return {
cashbook: {
expenditure: {},
income: {}
},
totals: {},
available: {}
}
},
componentDidMount: function () {
// Two way data binding
base.syncState('cashbook', {
context: this,
state: 'cashbook'
}).then(()=> {
// after syncing cashbook, calculate totals
this.setState({
totals: {
income: this.getTotal(this.state.cashbook.income),
expenditure: this.getTotal(this.state.cashbook.expenditure),
}
});
});
},
// Get total of obj income/expenditure
getTotal: function (obj) {
var expIds = Object.keys(obj);
return expIds.reduce((prevTotal, key) => {
var type = obj[key];
return prevTotal + (parseFloat(type.amount));
}, 0);
},
addCashflow: function (identifier, amount) {
var timestamp = (new Date()).getTime();
// clone cashbook and clone cashbook[identifier] and set cashbook[identifier][identifier + '-' + timestamp] to amount
var cashbook = {
...this.state.cashbook,
[identifier]: {
...this.state.cashbook[identifier],
[identifier + '-' + timestamp]: amount
}
};
// set state
this.setState({
cashbook: cashbook,
// Update totals
totals: {
...this.state.totals,
[identifier]: this.getTotal(cashbook[identifier])
}
});
},
removeCashflow: function (identifier, key) {
// clone cashbook and clone cashbook[identifier]
var cashbook = {...this.state.cashbook, [identifier]: {...this.state.cashbook[identifier]}};
delete cashbook[identifier][key];
this.setState({
cashbook: cashbook,
totals: {
...this.state.totals,
// Update totals
[identifier]: this.getTotal(cashbook[identifier])
}
});
},
render: function () {
return (
<div className="cashbook">
<Expenditure cashbook={this.state.cashbook.expenditure} removeCashflow={(key)=>this.removeCashflow('expenditure', key)}/>
<TotalCashflow total={this.state.cashbook.expenditure} identifier='expenditure'/>
{/*or drop TotalCashflow and do <h2 className="total">Total: {h.formatPrice(this.state.totals.expandature)}</h2>*/}
<AddForm addCashflow={(amount)=>this.addCashflow('expenditure', amount)}/>
<Income cashbook={this.state.cashbook.income} removeCashflow={(key)=>this.removeCashflow('income', key)}/>
<TotalCashflow type={this.state.cashbook.income} identifier='income' />
<AddForm addCashflow={(amount)=>this.addCashflow('income', amount)}/>
<Available totals={this.state.totals}/>
</div>
);
}
});
export default App;
Issues with your current App component
Issue: You are not removing the key, you're just setting it to null; this could lead to exceptions when iterating Object.keys() and you're expecting the values to be numbers, like when calculating the totals
removeIncome: function(key) {
// this.state.cashbook.income[key] = null;
delete this.state.cashbook.income[key]
this.setState({
cashbook: { income: this.state.cashbook.income }
});
},
Bad design: You're defining the markup of a child component within your parent component, although it seems unnecessary
renderExpenditure: function(key) {
var details = this.state.cashbook.expenditure[key];
return(
<tr className="item" key={key}>
<td><strong>{details.name}</strong></td>
<td><strong>{h.formatPrice(details.amount)}</strong></td>
<td>{details.category}</td>
<td>{details.type}</td>
<td>{details.date}</td>
<td><button className="remove-item" onClick={this.removeExpenditure.bind(null, key)}>Remove</button></td>
</tr>
);
},
This could easily be moved to your Expenditure/Income component.
Issues: Mutating state, Overwriting cashbook in state and loosing expenditure/income
addExpenditure: function(expenditure) {
var timestamp = (new Date()).getTime();
// You are mutating the state here, better clone the object and change the clone, then assign the cloned
this.state.cashbook.expenditure['expenditure-' + timestamp] = expenditure;
// You are overwriting cashbook with an object, that only contains expenditure, thus loosing other properties like income
this.setState({
cashbook: { expenditure: this.state.cashbook.expenditure }
});
}
// Fixed
addExpenditure: function(expenditure) {
var timestamp = (new Date()).getTime();
// clone object
var cashbook = Object.assign({}, this.state.cashbook);
cashbook.expenditure = Object.assign({}, cashbook.expenditure);
// define latest expenditure
cashbook.expenditure['expenditure-' + timestamp] = expenditure;
// set state
this.setState({
cashbook: cashbook
});
}
// ES6
addExpenditure: function(expenditure) {
var timestamp = (new Date()).getTime();
this.setState({
cashbook: {
...this.state.cashbook,
expenditure: {
...this.state.cashbook.expenditure,
['expenditure-' + timestamp]: expenditure
}
}
});
}
You would be better off, if you'd flatten your state and cashbook object
so instead of
this.state = {
cashbook: {
expenditure: {},
income: {}
},
totals: {},
available: {}
}
having
this.state = {
expenditure: {},
income: {}
totals: {},
available: {}
}
so you could just
addExpenditure: function(expenditure) {
var timestamp = (new Date()).getTime();
var exp = Object.assign({}, this.state.cashbook.expenditure);
exp['expenditure-' + timestamp] = expenditure;
this.setState({
expenditure: exp
});
}
or es6
addExpenditure: function(expenditure) {
var timestamp = (new Date()).getTime();
this.setState({
expenditure: {
...this.state.cashbook.expenditure,
['expenditure-' + timestamp]: expenditure
}
});
}
of course you'd need to update the rebase binding and your models, dunno if this is something you want
componentDidMount: function() {
base.syncState('expenditure', {
context: this,
state: 'expenditure'
});
base.syncState('income', {
context: this,
state: 'income'
});
}

Resources