修改程式剛執行的初始畫面
在src/navigator.js
新增一個MerchandiseList 畫面
import { StackNavigator } from 'react-navigation';
import Home from './containers/Home';
import Counter from './containers/Counter';
import Camera from './components/Camera';
import PersonalInfo from './components/PersonalInfo';
import MerchandiseList from './components/MerchandiseList';
import NewMerchandise from './components/NewMerchandise';
const AppNavigator = new StackNavigator(
{
Home: { screen: Home },
Counter: { screen: Counter },
Camera: { screen: Camera },
PersonalInfo: { screen: PersonalInfo },
MerchandiseList: { screen: MerchandiseList },
NewMerchandise: { screen: NewMerchandise }
},
{
headerMode: 'screen',
navigationOptions: {
header: null
}
}
);
export default AppNavigator;
src/reducers/nav.js
的 routes
中的routeName
來決定初始畫面
import AppNavigator from '../navigator';
const initialState = {
index: 0,
routes: [{ key: 'Init', routeName: 'MerchandiseList', params: {} }]
};
export default (state = initialState, action) =>
AppNavigator.router.getStateForAction(action, state);
使用Touchable 元件來增加回饋
使用src/components/__data__/merchandise_list.json
作為測試資料
import MOCKDATA from './__data_/merchandise_list.json
[
{
"picture_url": "https://cfshopeetw-a.akamaihd.net/file/08af7e4f7c83b53ee4d3acb2d1f19b88_tn",
"discount": 0.8,
"price": 200,
"stars": 6819,
"title":
"[免運] 多件優惠 MIT台灣製-防潑水多功能桌上螢幕架 桌上架 鍵盤架 收納架 電腦架 ㄇ型架 ST004 居家大師",
"count": 12
},
...
]
FlatList
keyExtractor (設置每個Item 的 Id)
使用TouchableOpacity
來實現Touch 的回饋與前往特定的頁面
renderItem = ({ item }) => (
<TouchableOpacity onPress={this.newMerchandise} activeOpacity={0.7}>
<View style={styles.listItem}>
<Image style={styles.thumbnail} source={ { uri: item.picture_url } } />
<Text numberOfLines={1} ellipsizeMode="tail" style={styles.itemText}>
{item.title}
</Text>
</View>
</TouchableOpacity>
);
state = {
data: MOCKDATA
}
render(){
return (
<View style={styles.container}>
<FlatList
style={styles.list}
keyExtractor={this.keyExtractor}
data={this.state.data}
renderItem={this.renderItem}
/>
<Button onPress={this.newMerchandise} title="新增商品" />
</View>
)
}
const styles = StyleSheet.create({
itemText: {
color: 'black',
fontSize: 22,
flex: 0.8
},
thumbnail: {
width: 72,
height: 72,
flex: 0.2
},
});
onRequestClose
當Android 上的 back 鍵觸發。
<Modal
animationType="slide"
transparent
visible={this.state.visible}
onRequestClose={() => {
this.setState({
visible: false
});
}}
>
{// Modal的內容,可以是個兩個按鈕的確認視窗 }
</Modal>
High Order Component 封裝了元件共用的行為,對行為做reuse ,而非對畫面做reuse
實現connectModal hoc,並把openModal 與 closeModal 傳入,方便WrappedComponent
使用
openModal 讓WrappedComponent
可以傳入自定義客製化的modalView
openModal 也讓WrappedComponent
當下的context,譬如說當下的list item
此Modal 並非blocking Modal,所以也實現了讓使用者點任意地方可以關掉此Modal,參考TouchableOpacity
的部分
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import {
StyleSheet,
View,
ViewPropTypes,
Text,
Modal,
TouchableWithoutFeedback,
TouchableOpacity
} from 'react-native';
const styles = StyleSheet.create({
container: {
flex: 1
},
modalView: {
flex: 1,
backgroundColor: '#333a'
},
closeModalView: {
position: 'absolute',
top: 0,
left: 0,
bottom: 0,
right: 0
}
});
const EmptyComponent = () => {};
export default function connectModal(WrappedComponent) {
return class AppModal extends Component {
state = {
visible: false,
modalView: EmptyComponent
};
openModal = ({ modalView, context }) => {
const ModalView = modalView || EmptyComponent;
this.setState({
modalView: () => <ModalView context={context} />,
visible: true
});
};
closeModal = () => {
this.setState({
visible: false
});
};
render() {
const WrappedContextModalView = this.state.modalView;
return (
<View style={styles.container}>
<WrappedComponent
{...this.props}
openModal={this.openModal}
closeModal={this.closeModal}
/>
<Modal
animationType="slide"
transparent
visible={this.state.visible}
onRequestClose={() => {
this.setState({
visible: false
});
}}
>
<View style={styles.modalView}>
<TouchableOpacity onPress={this.closeModal} style={styles.closeModalView} />
<WrappedContextModalView context={this.state.context} />
</View>
</Modal>
</View>
);
}
};
}
在需要使用此Modal 的Modal 在export 之前,掛上connectModal ,並在item 按下後,開啟Modal ,並傳入自定義的畫面。
import connectModal from './hoc/connectModal';
class MerchandiseList {
onMerchandisePress = (item) => {
this.props.openModal({ modalView: this.modal, context: item });
};
modal = ({ context }) => (
<View style={styles.modal}>
<View style={styles.buttonContainer}>
<Button
color="red"
title="刪除"
onPress={() => {
this.removeItem(context);
this.props.closeModal();
}}
/>
</View>
</View>
);
...
}
export default connectModal(MerchandiseList);
在按鈕被按下後,呼叫closeModal 的動作