Common problems encountered in React-Native development are summarized as follows. The following are the common problems I encountered in recent project development. I will make the following records for use in subsequent projects.
1. Listen for changes in the network connection status
componentDidMount () {
NetInfo.addEventListener('change'.this.handleConnectivityChange);
}
componentWillUnmount() {
NetInfo.removeEventListener('change'.this.handleConnectivityChange);
}
handleConnectivityChange() {
NetInfo.isConnected.fetch().then(netConnected= > {
if (netConnected) {
ToastAndroid.show('Network connected', ToastAndroid.SHORT, ToastAndroid.BOTTOM)
} else {
ToastAndroid.show('Please check network connection', ToastAndroid.SHORT, ToastAndroid.BOTTOM)
}
})
}
Copy the code
2. Handle the rollback button and physical rollback events on a special page
// Navigation didFocus willBlur event
// BackHandler hardwareBackPress event
/ / this. Props. Navigation. Replace (RouterName) routing to replace
/ / this. Props. Navigation. IsFocused () routing activated state
_didFocusSubscription;
_willBlurSubscription;
constructor (props) {
super(props)
this._didFocusSubscription = props.navigation.addListener('didFocus', payload =>
BackHandler.addEventListener('hardwareBackPress'.this.onBackButtonPressAndroid))
}
componentDidMount () {
this._willBlurSubscription = this.props.navigation.addListener('willBlur', payload => {
BackHandler.removeEventListener('hardwareBackPress'.this.onBackButtonPressAndroid)
})
}
componentWillUnmount () {
this._didFocusSubscription && this._didFocusSubscription.remove()
this._willBlurSubscription && this._willBlurSubscription.remove()
BackHandler.removeEventListener('hardwareBackPress'.this.onBackButtonPressAndroid)
}
onBackButtonPressAndroid = (a)= > {
if (this.toRouterName) {
this.props.navigation.replace(this.toRouterName)
return true
} else {
return false}};Copy the code
CreateStackNavigator, createBottomTabNavigator Route nested StackNavigator jump problem
// We need to re-pass the Navigation property to the TabNavigator to redefine the router of the TabNavigator container component as the router of the TabNavigator
class MainView extends Component {
static navigationOptions = {
header: null
};
render () {
let { isMask } = this.props.global
const { cartCount } = this.props
return (
<View>
<AppTabNavigator navigation={this.props.navigation}/>
</View>
)
}
}
MainView.router = AppTabNavigator.router
Copy the code
4. TabBarOnPress intercepts TAB click events for TAB navigation
navigationOptions: ({navigation, screenProps}) = > ({
title: 'I'.tabBarIcon: ({focused}) = > (
<Image
source={focused ? require('./images/ic_mine_checked.png') : require('./images/ic_mine.png')}
style={styles.tabIcon}
/>), tabBarOnPress: () => { if (! screenProps.netConnected) { navigation.navigate('Home') } } })Copy the code
5. Solve the problems of locking screen direction and TAB navigation by keyboard
<activity
android:name=".MainActivity"
android:label="@string/app_name"
android:configChanges="keyboard|keyboardHidden|orientation|screenSize"> add a line: android: screenOrientation ="portrait"Set portrait to lock portrait, landscape to lock landscape// The values in the dynamic render data object in the screenProps TAB navigation can be bound to values in redux
<AppTabNavigator screenProps={{cartCount: cartCount}} navigation={this.props.navigation}/>
Copy the code
6. Monitor routing events, which can be used to double click the physical back button to exit App and other functions
import { createStackNavigator, NavigationActions } from 'react-navigation'
import { ToastAndroid, BackHandler } from 'react-native'
const AppNavigator = createStackNavigator(routes, stackConfig)const defaultStateAction = AppNavigator.router.getStateForAction
let lastBackPressed = 0
AppNavigator.router.getStateForAction = (action, state) = > {
const backRouteName = state && state.routes[state.routes.length - 1].routeName
if (state && (action.type === NavigationActions.BACK) && (backRouteName === 'MainView')) {
if ((lastBackPressed + 2000) < Date.now()) {
ToastAndroid.show('Press Exit again', ToastAndroid.SHORT)
lastBackPressed = Date.now()
return { ...state }
}
BackHandler.exitApp()
}
return defaultStateAction(action, state)
}
Copy the code
7. Solve isMounted (…). is deprecated warning
import { YellowBox } from 'react-native'
YellowBox.ignoreWarnings(['Warning: isMounted(...) is deprecated'.'Module RCTImageLoader'])
Copy the code
8. The rational use of componentWillReceiveProps shouldComponentUpdate
componentWillReceiveProps (nextProps) {
if(! nextProps.xxx) { dosomething } } shouldComponentUpdate (newProps, newState) {if (this.props.navigation.isFocused()) {
return true // render
} else {
return false // not render}}Copy the code
9. Utility class Logger and Create Store
import { createStore, applyMiddleware, compose } from 'redux'
import screenTracking from './screenTrackingMiddleware'
import reducer from '.. /reducers'
import logger from 'redux-logger'
const middlewares = []
if (__DEV__) {
middlewares.push(logger)
}
middlewares.push(screenTracking)
conststore = compose(applyMiddleware(... middlewares))(createStore)(reducer)export default store
Copy the code
10. Useful third-party components
The react - native - swiper swiper components react - native - linear gradient ramp components react - native - swipe - list - the view sideslip components React-native image-crop-picker Image cropping, call camera and phone album react-native cookies manage cookiesCopy the code
11. The ScrollView component listens for scrolling to the bottom
_contentViewScroll (e) {
let offsetY = e.nativeEvent.contentOffset.y // Slide distance
let contentSizeHeight = e.nativeEvent.contentSize.height // scrollView contentSize Height
let oriageScrollHeight = e.nativeEvent.layoutMeasurement.height / / scrollView height
if (offsetY + oriageScrollHeight >= contentSizeHeight) {
// do something
}
}
<ScrollView
onMomentumScrollEnd={this._contentViewScroll.bind(this)}
showsVerticalScrollIndicator={false} ></ScrollView>
Copy the code
12. Image ADAPTS an Image to its width or height
class ImageAdaptive extends Component {
state = {
width: 0.height: 0
}
componentDidMount () {
Image.getSize(this.props.uri, (width, height) => {
let h = 330 * height / width
this.setState({height: h})
})
}
render () {
return (
<Image source={{uri: this.props.uri}} style={[{width: 330.height: this.state.height}, this.props.style]} / >)}}Copy the code
13. Picture preview component adapted from Swiper component
<Swiper
loop={false}
index={initialSlide}
renderPagination={(index, total) => (
<View style={styles.paginationStyle}>
<Text style={styles.paginationText}>{index + 1}/{total}</Text>
{
delImage
? <TouchableOpacity onPress={()= > { delImage && delImage(index) }} style={styles.del}>
<Image source={require('././images/personal/ic_preview_delete.png')} style={styles.imageDel} />
</TouchableOpacity> : null
}
</View>
)}>
{
images && images.map((image, index) => (
<TouchableOpacity style={styles.imagesItemWrapper} key={index} activeOpacity={1} onPress={this.closeModal}>
<Image resizeMode='contain' style={styles.imagesItem} source={{ uri: image}} / >
</TouchableOpacity>))}</Swiper>
Copy the code