反应Redux Saga API调用

时间:2018-09-17 10:43:54

标签: api react-native redux-saga

我正在使用 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;
  }
};

1 个答案:

答案 0 :(得分:0)

我发现了错误。它在 Saga / index.js 中。我在rootSaga()中没有正确呼叫sagas。我将其更改为yield all([call (saga1),call(saga2)...,call(saga11)])