- React Native Blueprints
- Emilio Rodriguez Martinez
- 681字
- 2021-07-02 15:19:59
Adding event handlers
All the interaction with the user will happen through event handlers in React Native. Depending on the controller, we will have different events which can be triggered. The most common event is onPress, as it will be triggered every time we push a button, a checkbox, or a view in general. Let's add some onPress handlers for all the components which can be pushed in our screen:
/*** ShoppingList.js ***/
...
render() {
return (
<Container>
<Content>
<List>
{this.state.products.map(p => {
return (
<ListItem
key={p.id}
onPress={this._handleProductPress.bind(this, p)}
>
<Body>
<Text style={{ color: p.gotten ? '#bbb' : '#000' }}>
{p.name}
</Text>
</Body>
<Right>
<CheckBox
checked={p.gotten}
onPress={this._handleProductPress.bind(this, p)}
/>
</Right>
</ListItem>
);
})}
</List>
</Content>
<Fab
style={{ backgroundColor: '#5067FF' }}
position="bottomRight"
onPress={this._handleAddProductPress.bind(this)}
>
<Icon name="add" />
</Fab>
<Fab
style={{ backgroundColor: 'red' }}
position="bottomLeft"
onPress={this._handleClearPress.bind(this)}
>
<Icon ios="ios-remove" android="md-remove" />
</Fab>
</Container>
);
}
...
Notice we added three onPress event handlers:
- On <ListItem>, to react when the user taps on one product in the list
- On <CheckBox>, to react when the user taps on the checkbox icon next to every product in the list
- On both the <Fab> buttons
If you know React, you probably understand why we use .bind in all our handler functions, but, in case you have doubts, .bind will make sure we can use this inside the definition of our handlers as a reference to the component itself instead of the global scope. This will allow us to call methods inside our components as this.setState or read our component's attributes, such as this.props and this.state.
For the cases when the user taps on a specific product, we also bind the product itself, so we can use them inside our event handlers.
Now, let's define the functions which will serve as event handlers:
/*** ShoppingList.js ***/
...
_handleProductPress(product) {
this.state.products.forEach(p => {
if (product.id === p.id) {
p.gotten = !p.gotten;
}
return p;
});
this.setState({ products: this.state.products });
}
...
First, let's create a handler for when the user taps on a product from our shopping list or in its checkbox. We want to mark the product as gotten (or unmark it if it was already gotten), so we will update the state with the product marked properly.
Next, we will add a handler for the blue <Fab> button to navigate to the AddProduct screen:
/*** ShoppingList.js ***/
...
_handleAddProductPress() {
this.props.navigation.navigate('AddProduct', {
addProduct: product => {
this.setState({
products: this.state.products.concat(product)
});
},
deleteProduct: product => {
this.setState({
products: this.state.products.filter(p => p.id !== product.id)
});
},
productsInList: this.state.products
});
}
...
This handler uses this.props.navigation, which is a property automatically passed by the Navigator component from react-navigation. This property contains a method named navigate, receiving the name of the screen to which the app should navigate plus an object which can be used as a global state. In the case of this app, we will store three keys:
- addProduct: One function to allow the AddProduct screen to modify the ShoppingList component's state to reflect the action of adding a new product to the shopping list.
- deleteProduct: One function to allow the AddProduct screen to modify the ShoppingList component's state to reflect the action of removing a product from the shopping list.
- productsInList: A variable holding the list of products is already on the shopping list, so the AddProducts screen can know which products were already added to the shopping list and display those as "already added", preventing the addition of duplicate items.
Handling state within the navigation should be seen as a workaround for simple apps containing a limited number of screens. In larger apps (as we will see in later chapters), a state management library, such as Redux or MobX, should be used to keep the separation between pure data and user interface handling.
We will add the last handler for the blue <Fab> button, which enables the user to clear all the items in the shopping list in case you want to start a new list:
/*** ShoppingList.js ***/
...
_handleClearPress() {
Alert.alert('Clear all items?', null, [
{ text: 'Cancel' },
{ text: 'Ok', onPress: () => this.setState({ products: [] }) }
]);
}
...
We are using Alert to prompt the user for confirmation before clearing all the elements in our shopping list. Once the user confirms this action, we will empty the products attribute in our component's state.
- Mastering vRealize Operations Manager(Second Edition)
- Windows Server 2019 Cookbook
- 白話區塊鏈
- Learning Android Intents
- 循序漸進學Docker
- Windows Phone 8 Application Development Essentials
- Delphi Programming Projects
- Linux軟件管理平臺設計與實現
- Multi-Cloud for Architects
- Linux集群之美
- Azure Resource Manager Templates Quick Start Guide
- Windows網絡編程(第2版)
- 15分鐘!畫出我的漫畫角色:賣萌篇
- 程序員必讀經典(算法基礎+計算機系統)
- Instant Responsive Web Design