我正在使用 react-native 构建送餐应用程序,其中需要显示API调用中的餐厅列表。我决定不久前使用 Redux-saga 实施它。 在Github上搜索了教程和不同示例之后,我无法理解这个概念。因此,我的问题是,如何确保在从登录屏幕导航到主屏幕时调度操作,该操作根据API响应在主屏幕中按需要显示餐厅,或者更具体地说将API响应存储在saga索引中并在主屏幕中访问它。对不起,代码混乱(仍然是初学者)。对于出现的错误,我事先表示歉意(我第一次在这里问)。
src / Sagas / index.js
import { put, delay, call } from "redux-saga/effects";
import { takeEvery, takeLatest } from "redux-saga";
import axios from "axios";
export function* incrementAsync() {
yield delay(1000);
yield put({ type: "INCREMENT" });
}
export function* fetchRestaurantAsync() {
try {
console.log("Calling API");
const response = yield call(
axios.get,
"http://18.188.213.236/fooddelivery/api_v2/Homemaster/getCategories/0/1/25.204849/55.27078"
);
console.log("reponse", response);
yield put({ type: "FETCH_SUCCEEDED" }, restaurant);
const restaurant = response ? response.data.category : [];
// const data = yield call(Api.fetchUser, action.payload.url);
// yield put({ type: "FETCH_SUCCEEDED", data });
} catch (error) {
console.log("requestfailed: could not ");
console.log("error", error);
// yield put({ type: "FETCH_FAILED", error });
}
}
export function* watchfetchRestaurant() {
yield takeEvery("FETCH_REQUESTED", fetchRestaurantAsync);
}
export function* watchCart() {
yield takeEvery("INCREMENT_ASYNC", incrementAsync);
}
export default function* rootSaga() {
yield { watchCart };
yield { watchfetchRestaurant };
}
src / components / Home.js
import React, { Component } from "react";
import { Text, View, ScrollView, Image, StyleSheet } from "react-native";
import { Container, Card, CardItem, Body, Left, Right } from "native-base";
import RestaurantDetail from "./RestaurantDetail";
import axios from "axios";
import { connect } from "react-redux";
import LinearGradient from "react-native-linear-gradient";
import { SafeAreaView } from "react-navigation";
class Home extends Component {
constructor(props) {
super(props);
this.state = {
banner: [],
nearByRestaurant: []
};
axios
.get(
"http://18.188.213.236/fooddelivery/api_v2/Bannermaster/getBannerList/{latitude}/{longitude}"
)
.then(response => {
this.setState({ banner: response.data.result });
})
.catch(function(error) {
console.log(
"There has been a problem with your fetch operation: " + error
);
throw error;
});
axios
.get(
"http://18.188.213.236/fooddelivery/api_v2/Restaurantmaster/get_restaurants/0/25.204849/55.27078"
)
.then(response => {
console.log(response);
this.setState({ nearByRestaurant: response.data.result });
})
.catch(function(error) {
console.log(
"There has been a problem with your fetch operation: " + error
);
throw error;
});
}
renderRestaurants() {
return this.props.restaurant.map(restaurants => {
return restaurants.dishes.map(dishes => (
<RestaurantDetail key={dishes.dish_id} dishes={dishes} />
));
});
}
renderBanner() {
return (
<ScrollView
contentContainerStyle={{ flexDirection: "row" }}
horizontal={true}
>
{this.state.banner.map(result => {
return (
<View
key={result.id}
style={{
justifyContent: "center",
alignItems: "center"
}}
>
<Image
resizeMode="cover"
source={{
uri: result.image
}}
style={{ position: "relative", height: 300, width: 400 }}
/>
<Text style={styles.bannertextStyle}>{result.messages}</Text>
</View>
);
})}
</ScrollView>
);
}
rendernearByRestaurant() {
return (
<View>
<ScrollView
contentContainerStyle={{ flexDirection: "row" }}
horizontal={true}
showsHorizontalScrollIndicator={false}
>
{this.state.nearByRestaurant.map(result => {
return (
<Card
key={result.restaurant_id}
style={{
height: 200,
width: 230,
backgroundColor: "transparent"
}}
>
<Body>
<Image
resizeMode="cover"
source={{
uri: result.image
}}
style={{
height: 150,
width: 220,
borderRadius: 5
}}
/>
</Body>
<CardItem
footer
style={{ height: 50, backgroundColor: "transparent" }}
>
<Left>
<Text numberOfLines={1}>{result.restaurant_name}</Text>
</Left>
<Right>
<Text numberOfLines={1} style={{ textAlign: "center" }}>
{result.start_price +
"-" +
result.end_price +
" " +
"USD"}
</Text>
</Right>
</CardItem>
</Card>
);
})}
</ScrollView>
</View>
);
}
render() {
console.log(this.props);
return (
<SafeAreaView>
<View styles={styles.containerStyle}>
<ScrollView>
<ScrollView horizontal={true}>
<View styles={styles.bannerStyle}>{this.renderBanner()}</View>
</ScrollView>
<View>
<LinearGradient
style={{
height: 100,
borderColor: "transparent"
}}
locations={[0.4, 0.8]}
colors={["#FF8500", "#FB3D2D"]}
start={{ x: 0, y: 0 }}
end={{ x: 1, y: 0 }}
>
<View
style={{
flexDirection: "row",
alignContent: "flex-end",
justifyContent: "space-between"
}}
>
<Text
style={{
fontFamily: "Poppins",
fontWeight: "600",
color: "white",
fontSize: 20
}}
>
Rigel Picks
</Text>
<Image source={require("../assets/ios/filter.png")} />
</View>
</LinearGradient>
</View>
<View>
<View style={{ padding: 10 }}>
//Saga Api response as 'restaurant' here
<RestaurantDetail
restaurants={this.props.restaurant.slice(0, 1)}
navigations={this.props.navigation}
/>
</View>
<View style={{ flex: 1, padding: 10 }}>
<LinearGradient
style={{
borderColor: "transparent",
borderRadius: 8,
flex: 1
}}
locations={[0.4, 0.8]}
colors={["#FF8500", "#FB3D2D"]}
start={{ x: 0, y: 0 }}
end={{ x: 1, y: 0 }}
>
<CardItem header style={{ backgroundColor: "transparent" }}>
<Left>
<Text
style={{
textAlign: "left",
fontSize: 18,
color: "white",
fontWeight: "bold"
}}
>
Near By Restaurants
</Text>
</Left>
<Right>
<Text style={styles.linkStyle}>See all</Text>
</Right>
</CardItem>
<CardItem style={{ backgroundColor: "transparent" }}>
<View>{this.rendernearByRestaurant()}</View>
</CardItem>
</LinearGradient>
</View>
<View style={{ borderRadius: 8, padding: 10 }}>
//Saga Api response as 'restaurant' here
<RestaurantDetail
restaurants={this.props.restaurant.slice(1)}
navigations={this.props.navigation}
/>
</View>
</View>
</ScrollView>
</View>
</SafeAreaView>
);
}
}
const styles = StyleSheet.create({
containerStyle: { flex: 1, backgroundColor: "transparent" },
bannerStyle: {
flex: 2,
alignContent: "center",
fontSize: 20,
fontWeight: "bold"
},
bannertextStyle: {
fontFamily: "Poppins",
position: "absolute",
top: 40,
fontSize: 30,
color: "white",
textTransform: "uppercase",
fontWeight: "bold"
},
gradientStyle: {
height: 30,
fontSize: 5,
fontWeight: "bold"
},
categoryRestaurantStyle: {
borderRadius: 3,
justifyContent: "space-between",
alignContent: "center"
},
imageStyle: {
height: 100,
width: 100
},
restaurantNameStyle: {
fontSize: 15,
fontWeight: "bold"
},
dishnameStyle: {
fontSize: 5,
fontWeight: "bold"
},
fontcolorStyle: {
color: "white"
},
linkStyle: {
fontFamily: "Poppins",
fontSize: 18,
color: "white",
textDecorationLine: "underline"
}
});
function mapStateToPros(state) {
return {
restaurant: state.restaurant
};
}
const HomeComponent = connect(
mapStateToPros,
null
)(Home);
export { HomeComponent as Home };
src / components / Reducers / index.js
import { combineReducers } from "redux";
import counterReducer from "./counterReducer";
import fetchReducer from "./fetchReducer";
export default combineReducers({
ctr: counterReducer,
fetch: fetchReducer
});
src / components / Reducers / fetchReducer.js
export default (state = { restaurant: [] }, action) => {
switch (action.type) {
case "FETCH_REQUESTED":
case "FETCH_SUCCEEDED":
return {
...state,
restaurant: action.payload
};
case "FETCH_FAILED":
return {
...state,
restaurant: []
};
default:
return state;
}
};
答案 0 :(得分:0)
我发现了错误。它在 Saga / index.js 中。我在rootSaga()
中没有正确呼叫sagas。我将其更改为yield all([call (saga1),call(saga2)...,call(saga11)])
。