Reputation: 453
class CreateTS extends Component {
constructor(props) {
super(props);
this.state = {
project: 'Select Project',
activity: 'Select Activity',
hour: '',
task: '',
timesheet: [],
dataSource: []
};
const ds = new ListView.DataSource({
rowHasChanged: (r1, r2) => r1 !== r2
});
this.state.dataSource = ds.cloneWithRows(this.state.timesheet);
console.log('Here at constructo!');
}
onAddTSPress() {
const { project, activity, task, hour } = this.state;
console.log(project);
console.log(activity);
console.log(task);
console.log(hour);
this.setState({
timesheet: this.state.timesheet.push(project)
});
console.log('Here button press!');
const ds = new ListView.DataSource({
rowHasChanged: (r1, r2) => r1 !== r2
});
this.dataSource = ds.cloneWithRows(this.state.timesheet);
}
renderRow(data) {
console.log('Here at render row!');
console.log(`${data} $""`);
return <Text> {data} </Text>;
}
render() {
return(
Some input components that set state of project and activity with
values...
A button that call onAddTSPress function.
And a listview in which items will be add that we created above
);
}
After running above code and add one item i got following screen which is expected behavior.
But when i try to add another item in list i got following error. What is the issue?
it saying push is not a function while first time it run successfully as expected. But second time it gives error and i am unable to add second item in list.
Here is my updated onAddTSPress function
//Modified onAddTSPress function
onAddTSPress() {
const { project, activity, task, hour } = this.state;
console.log(project);
console.log(activity);
console.log(task);
console.log(hour);
console.log(`${this.state.timesheet}`);
this.setState({
timesheet: [...this.state.timesheet, project]
});
console.log('Here button press!');
console.log(`${this.state.timesheet}`);
this.setState({ dataSource:
this.state.dataSource.cloneWithRows(this.state.timesheet) });
}
return (
<Button
onPress={this.onAddTSPress.bind(this)}
btnStyle={styles.btnStyle}
txtStyle={styles.txtStyle}
>
Add
</Button>
<ListView
style={styles.listViewContianer}
dataSource={this.state.dataSource}
renderRow={this.renderRow}
enableEmptySections
/>
);
Upvotes: 1
Views: 2569
Reputation: 3141
You are calling this.state.timesheet.push(project)
, push
prototype of array return number of record in array after pushed. push
method not returning latest array and you are setting state with return value of push
method which are a number. First time it work fine because you initialize timesheet as array ([]
) and first time push
method work. But second time when you try to call push
method of timesheet
, which is now a number, it will throw array.
You can try [...this.state.timesheet, project]
instance of push. By this way you will get updated array.
this.setState({
timesheet: [...this.state.timesheet, project]
});
or
You can keep old value in a variable and push new value and reassign array to setState.
const timesheet = this.state.timesheet;
timesheet.push(project);
this.setState({
timesheet: timesheet
});
Also use datasource inside state and update it by setState
const ds = new ListView.DataSource({
rowHasChanged: (r1, r2) => r1 !== r2
});
this.setState({
dataSource: ds.cloneWithRows(this.state.timesheet)
});
Upvotes: 1
Reputation: 6223
You should never mutate state directly, instead use following syntax
this.setState(prevState => ({
timesheet: [...prevState.timesheet, project]
}))
For your comment:
First item added in list after second click and second after third click and so on
You need to re-render ListView
on state change. To do so you can either add key like
key="this.state.listChanged" // your list state name
or
(this.state.listChanged)
? <ListView />{/* or call your method */}
: <Text>{/*some message */}</Text>
Upvotes: 1