- 安装axios
yarn add axios
- 封装request.js
import axios from 'axios'
import Config from "react-native-config";
const service = axios.create({
baseURL: Config.API_URL,
timeout: 30000 // request timeout
})
service.interceptors.request.use(
config => {
if (config.params) {
console.log(config.url, config.params)
} else if (config.data) {
console.log(config.url, config.data)
} else {
console.log(config.url)
}
return config
},
error => {
console.log(error)
return Promise.reject(error)
}
)
service.interceptors.response.use(
response => {
const res = response.data
console.log(res)
if (res.code !== 200) {
return Promise.reject(res)
} else {
return res
}
},
error => {
console.log('err' + error) // for debug
return Promise.reject(error)
}
)
export default service
import request from '@/config/request';
/**
* 轮播图数据
* @param params
* @returns
*/
export async function getBannerList(): Promise<any> {
return request({
url: '/home/banner',
method: 'GET',
});
}
- 在dva的model中使用
import { Model, Effect } from 'dva-core-ts'
import { Reducer } from 'redux'
//导入service远端数据请求
import { getBannerList } from '@/pages/home/service'
import type { BannerType } from '@/pages/home/data'
type HomeState = {
banners: BannerType[]
}
interface HomeModelType extends Model {
namespace: string
state: HomeState;//封装后台返回的数据
effects: {
asyncBannerList: Effect;
};
reducers: {
getBannerList: Reducer<HomeState>,
};
}
const HomeModel: HomeModelType = {
namespace: 'home',
state: {
banners: []
},
//异步
effects: {
*asyncBannerList({ _ }, { call, put }) {
const response = yield call(getBannerList)
if (response && response instanceof Object) {
yield put({
type: 'getBannerList',
payload: {
banners: response.data
}
})
}
},
},
//同步
reducers: {
getBannerList(state, action) {
return {
...state,
...action.payload,
};
},
}
}
export default HomeModel
- data.d.ts数据类型
/**
* 获取banner
*/
export type BannerType = {
id?: string,
image?: string
}
- 主页面调用dva,并将数据传递给轮播图组件
import React, { Component } from 'react';
import { View } from 'react-native';
import { RootStackNavigation } from '@/navigator/index'
// 使用dva
import { connect } from 'react-redux'
import type { ConnectedProps } from 'react-redux'
import type { RootState } from '@/models/index'
//轮播通用
import Carrousel from './components/carrousel'
// 关联dva
const mapStateToProps = ({ home, loading }: RootState) => {
return {
datas: home,//这里的home就是model中的namespace
loading: loading.effects['home/asyncAdd'] //指定哪个方法需要显示loading判断
}
}
//这里需要connect对象
const connector = connect(mapStateToProps)
//自动推导dva中的state类型
type ModelState = ConnectedProps<typeof connector>
// 这里需要继承ModelState ,区别于antd pro中的umi.js umi不需要
// antd umi.js中使用dva:https://huangxiaoguo.blog.csdn.net/article/details/114890454
interface IProps extends ModelState {
navigation: RootStackNavigation
}
class Home extends Component<IProps> {
componentDidMount() {
const { dispatch } = this.props
dispatch({
type: 'home/asyncBannerList'
})
}
// 跳转详情页
onPress = () => {
const { navigation } = this.props
navigation.navigate("Detail", { id: 18 })
}
render() {
const { datas, loading } = this.props
return (
<View>
<Carrousel banners={datas.banners} />
</View>
);
}
}
// export default Home;
export default connector(Home)
- 显示banner
import React, { Component } from 'react';
import SnapCarousel, { ParallaxImage, Pagination } from 'react-native-snap-carousel'
import type { AdditionalParallaxProps } from 'react-native-snap-carousel'
import { hp, viewportWidth, wp } from '@/utils/index'
import { StyleSheet, View } from 'react-native'
import { BannerType } from "../../data"
const sliderWidth = viewportWidth
const sideHeight = hp(26)
const itemWidth = wp(90) + wp(2) * 2
type CarouselProps = {
banners: BannerType[]
}
class Carousel extends Component<CarouselProps>{
state = {
activeSlide: 0
}
onSnapToItem = (index: number) => {
this.setState({
activeSlide: index
})
}
renderItem = ({ item }: { item: BannerType }, parallaxProps?: AdditionalParallaxProps) => {
return <ParallaxImage
source={{ uri: item.image }}
style={styles.image}
containerStyle={styles.imageContainer}
parallaxFactor={0.8}//默认0.3
showSpinner
spinnerColor='rgba(0,0,0,0.25)'
{...parallaxProps} />
}
get pagination() {
const { activeSlide } = this.state
const { banners } = this.props
return (
<View style={styles.paginationWarpper}>
<Pagination
containerStyle={styles.paginationContainer}
dotContainerStyle={styles.dotContainer}
dotStyle={styles.dot}
inactiveDotScale={0.7}
inactiveDotOpacity={0.4}
activeDotIndex={activeSlide}
dotsLength={banners.length} />
</View>
)
}
render() {
const { banners } = this.props
return (
<View>
<SnapCarousel data={banners}
renderItem={this.renderItem}
sliderWidth={sliderWidth}
itemWidth={itemWidth}
hasParallaxImages
loop
autoplay
onSnapToItem={this.onSnapToItem}
/>
{this.pagination}
</View>
);
}
}
const styles = StyleSheet.create({
imageContainer: {
width: itemWidth,
height: sideHeight,
borderRadius: 8
},
image: {
...StyleSheet.absoluteFillObject,
resizeMode: 'cover'
},
paginationWarpper: {
position: 'relative',
justifyContent: 'center',
alignItems: 'center'
},
paginationContainer: {
position: 'absolute',
top: -25,
backgroundColor: 'rgba(0,0,0,0.15)',
paddingHorizontal: 3,
paddingVertical: 4,
borderRadius: 8
},
dotContainer: {
marginHorizontal: 6
},
dot: {
width: 6,
height: 6,
borderRadius: 3,
backgroundColor: 'rgba(255,255,255,0.75)'
}
})
export default Carousel;
- 请求数据格式
{
"code": 200,
"data": [
{
"id": "2131231231232",
"image": "https://unsplash.it/1920/1080?random&56"
},
{
"id": "2131231233432",
"image": "https://unsplash.it/1920/1080?random&25"
},
{
"id": "21312343231232",
"image": "https://unsplash.it/1920/1080?random&3"
},
{
"id": "2131236631232",
"image": "https://unsplash.it/1920/1080?random&33"
},
{
"id": "2131987831232",
"image": "https://unsplash.it/1920/1080?random&22"
},
{
"id": "2131237651232",
"image": "https://unsplash.it/1920/1080?random&51"
}
],
"message": "获取数据成功"
}
- 效果