在React Native listView中动态添加和删除行

时间:2017-09-26 10:10:58

标签: reactjs react-native

 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
  );
}

运行上面的代码并添加一个项目,我得到了跟随屏幕,这是预期的行为。 enter image description here

但是当我尝试在列表中添加另一个项目时,我遇到了以下错误。有什么问题? enter image description here

它说第一次按预期成功运行时,push不是一个函数。但第二次它出错,我无法在列表中添加第二项。

这是我更新的onAddTSPress功能

   //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
            />


   );

2 个答案:

答案 0 :(得分:1)

你不应该直接改变状态,而是使用以下语法

this.setState(prevState => ({
  timesheet: [...prevState.timesheet, project]
}))

征求意见:

  

第二次点击后第一项添加到列表中,第三项后第二项添加   点击等等

您需要在状态更改时重新呈现ListView。为此,您可以添加像

这样的键
key="this.state.listChanged" // your list state name 

(this.state.listChanged)
  ? <ListView />{/* or call your method */}
  : <Text>{/*some message */}</Text>

答案 1 :(得分:0)

在推送之后,您正在调用this.state.timesheet.push(project)push数组的原型返回数组中的记录数。 push方法不返回最新数组,并且您正在设置状态,其返回值为push方法,这是一个数字。第一次它工作正常,因为您将时间表初始化为数组([])和第一次push方法工作。但是当你第二次尝试调用push的{​​{1}}方法时,它现在是一个数字,它会抛出数组。

解决方案

您可以尝试timesheet推送实例。通过这种方式,您将获得更新的阵列。

[...this.state.timesheet, project]

您可以在变量中保留旧值并推送新值并将数组重新分配给setState。

this.setState({
    timesheet: [...this.state.timesheet, project]
});

还在状态内使用datasource并通过setState

更新它
const timesheet = this.state.timesheet;
timesheet.push(project);
this.setState({
    timesheet: timesheet
});