Let's look at how I created this component:
// Tasks/app/components/TasksList/index.js
...
import TasksListCell from '../TasksListCell';
...
export default class TasksList extends Component {
...
async _addTask () {
const singleTask = {
completed: false,
text: this.state.text
}
Firstly, tasks are now represented as objects within the array. This allows us to add properties to each task, such as its completed state, and leaves room for future additions.
const listOfTasks = [...this.state.listOfTasks, singleTask];
await AsyncStorage.setItem('listOfTasks',
JSON.stringify(listOfTasks));
this._updateList();
}
...
_renderRowData (rowData, rowID) {
return (
<TasksListCell
completed={ rowData.completed }
id={ rowID }
onPress={ (rowID) => this._completeTask(rowID) }
text={ rowData.text }
/>
)
}
...
}
The _renderRowData method is also updated to render a new TasksListCell component. Four props are shared to TasksListCell: the task's completed state, its row identifier (provided by renderRow), a callback to alter the task's completed state, and the details of that task itself.
Here's how that TasksListCell component was written:
// Tasks/app/components/TasksListCell/index.js
import React, { Component, PropTypes } from 'react';
import {
Text,
TouchableHighlight,
View
} from 'react-native';
export default class TasksListCell extends Component {
static propTypes = {
completed: PropTypes.bool.isRequired,
id: PropTypes.string.isRequired,
onLongPress: PropTypes.func.isRequired,
onPress: PropTypes.func.isRequired,
text: PropTypes.string.isRequired
}
Use PropTypes to explicitly declare the data this component expects to be given. Read on for an explanation on prop validation in React.
constructor (props) {
super (props);
}
render () {
const isCompleted = this.props.completed ? 'line-through' : 'none';
const textStyle = {
fontSize: 20,
textDecorationLine: isCompleted
};
Use a ternary operator to calculate styling for a task if it is completed.
return (
<View>
<TouchableHighlight
onPress={ () => this.props.onPress(this.props.id) }
underlayColor={ '#D5DBDE' } >
<Text style={ textStyle }>{ this.props.text }</Text>
</TouchableHighlight>
</View>
)
}
}
The preceding component provides a TouchableHighlight for each task on the list, giving us visual opacity feedback when an item is tapped on. It also fires the _completeTask method of TasksListCell, which subsequently calls the onPress prop that was passed to it and makes a visual change to the style of the cell, marking it completed with a line through the horizontal center of the task.