Мои редукторы продолжают возвращаться неопределенными, несмотря на тот факт, что к данным обращаются - PullRequest
0 голосов
/ 13 мая 2019

Я работаю над приложением React Native, у которого есть работающая функция входа в Facebook, создатель действий и редуктор работают просто отлично, но создатели действий и редукторы для API поиска работы, который я использую, не работают .

Это создатели действий:

import axios from "axios";
// import { Location } from "expo";
import qs from "qs";

import { FETCH_JOBS, LIKE_JOB } from "./types";
import locationify from "../tools/locationify";

const JOB_ROOT_URL = "https://authenticjobs.com/api/?";

const JOB_QUERY_PARAMS = {
  api_key: "<api_key>",
  method: "aj.jobs.search",
  perpage: "10",
  format: "json",
  keywords: "javascript"
};

const buildJobsUrl = () => {
  const query = qs.stringify({ ...JOB_QUERY_PARAMS });
  return `${JOB_ROOT_URL}${query}`;
};

export const fetchJobs = (
  region,
  distance = 10,
  callback
) => async dispatch => {
  try {
    const url = buildJobsUrl();
    let job_list = await axios.get(url);
    job_list = locationify(
      region,
      console.log(job_list.data.listings.listing),
      job_list.data.listings.listing,
      distance,
      (obj, coords) => {
        obj.company.location = { ...obj.company.location, coords };
        return obj;
      }
    );
    dispatch({ type: FETCH_JOBS, payload: job_list });
    callback();
  } catch (e) {
    console.log("fetchJobs Action Error:", e.message);
  }
};

export const likeJob = job => {
  return {
    payload: job,
    type: LIKE_JOB
  };
};

Это jobs_reducer.js:

import { FETCH_JOBS } from "../actions/types";

const INITIAL_STATE = {
  listings: []
};

export default function(state = INITIAL_STATE, action) {
  switch (action.type) {
    case FETCH_JOBS:
      return action.payload;
    default:
      return state;
  }
}

Это likes_reducer.js:

import _ from "lodash";
import { LIKE_JOB } from "../actions/types";

export default function(state = [], action) {
  switch (action.type) {
    case LIKE_JOB:
      return _.uniqBy([action.payload, ...state], "id");
    default:
      return state;
  }
}

Я потратил весь вечер вчера на отладку этого, и все, что я знаю, это то, что я записываю данные консоли на свой терминал, я могу видеть детали данных API заданий, просто заполняющих мой терминал, но сообщение об ошибке состоит в том, что редукторы возвращаются не определено.

Как я могу вернуть данные и вернуть неопределенное одновременно?

Я использую создателя асинхронных действий. Нужно ли redux-thunk в приложении React Native? Использую ли я версию React Native с ошибкой прямо сейчас? Я знаю, как Redux должен работать, и поэтому я в тупике.

В reducers/index.js:

import { combineReducers } from "redux";
import auth from "./auth_reducer";
import jobs from "./jobs_reducer";
import likedJobs from "./likes_reducer";

export default combineReducers({
  auth,
  jobs,
  likedJobs
});

Где я начинаю получать эту ошибку или на что ссылается ошибка, это this.props.data.map() как в components/Swipe.js:

import React, { Component } from "react";
import {
  View,
  Animated,
  PanResponder,
  Dimensions,
  LayoutAnimation,
  UIManager
} from "react-native";

const SCREEN_WIDTH = Dimensions.get("window").width;
const SWIPE_THRESHOLD = 0.25 * SCREEN_WIDTH;
const SWIPE_OUT_DURATION = 250;

class Swipe extends Component {
  static defaultProps = {
    onSwipeRight: () => {},
    onSwipeLeft: () => {},
    keyProp: "id"
  };

  constructor(props) {
    super(props);

    const position = new Animated.ValueXY();
    const panResponder = PanResponder.create({
      onStartShouldSetPanResponder: (event, gestureState) => true,
      onPanResponderMove: (event, gestureState) => {
        position.setValue({ x: gestureState.dx, y: gestureState.dy });
      },
      onPanResponderRelease: (event, gestureState) => {
        if (gestureState.dx > SWIPE_THRESHOLD) {
          this.forceSwipe("right");
        } else if (gestureState.dx < -SWIPE_THRESHOLD) {
          this.forceSwipe("left");
        } else {
          this.resetPosition();
        }
      }
    });

    this.state = { panResponder, position, index: 0 };
  }

  componentWillReceiveProps(nextProps) {
    if (nextProps.data !== this.props.data) {
      this.setState({ index: 0 });
    }
  }

  componentWillUpdate() {
    UIManager.setLayoutAnimationEnabledExperimental &&
      UIManager.setLayoutAnimationEnabledExperimental(true);
    LayoutAnimation.spring();
  }

  forceSwipe(direction) {
    const x = direction === "right" ? SCREEN_WIDTH : -SCREEN_WIDTH;
    Animated.timing(this.state.position, {
      toValue: { x, y: 0 },
      duration: SWIPE_OUT_DURATION
    }).start(() => this.onSwipeComplete(direction));
  }

  onSwipeComplete(direction) {
    const { onSwipeLeft, onSwipeRight, data } = this.props;
    const item = data[this.state.index];
    direction === "right" ? onSwipeRight(item) : onSwipeLeft(item);
    this.state.position.setValue({ x: 0, y: 0 });
    this.setState({ index: this.state.index + 1 });
  }

  resetPosition() {
    Animated.spring(this.state.position, {
      toValue: { x: 0, y: 0 }
    }).start();
  }

  getCardStyle() {
    const { position } = this.state;
    const rotate = position.x.interpolate({
      inputRange: [-SCREEN_WIDTH * 1.5, 0, SCREEN_WIDTH * 1.5],
      outputRange: ["-120deg", "0deg", "120deg"]
    });
    return {
      ...position.getLayout(),
      transform: [{ rotate }]
    };
  }

  renderCards() {
    if (this.state.index >= this.props.data.length) {
      return this.props.renderNoMoreCards();
    }

    return this.props.data
      .map((item, i) => {
        if (i < this.state.index) {
          return null;
        }

        if (i === this.state.index) {
          return (
            <Animated.View
              key={item[this.props.id]}
              style={[this.getCardStyle(), styles.cardStyle]}
              {...this.state.panResponder.panHandlers}
            >
              {this.props.renderCard(item)}
            </Animated.View>
          );
        }
        return (
          <Animated.View
            key={item[this.props.id]}
            style={[styles.cardStyle, { top: 10 * (i - this.state.index) }]}
          >
            {this.props.renderCard(item)}
          </Animated.View>
        );
      })
      .reverse();
  }

  render() {
    return <View>{this.renderCards()}</View>;
  }
}

const styles = {
  cardStyle: {
    position: "absolute",
    width: SCREEN_WIDTH
  }
};

export default Swipe;

Выше я понял, что this.props.data.map() либо не определено, либо не является функцией.

Я получаю ту же проблему в ReviewScreen.js:

import React, { Component } from "react";
import { View, Text, Button, ScrollView } from "react-native";
import { connect } from "react-redux";

class ReviewScreen extends Component {
  static navigationOptions = ({ navigation }) => ({
    headerTitle: "Review Jobs",
    headerRight: (
      <Button
        title="Settings"
        onPress={() => {
          navigation.navigate("settings");
        }}
      />
    )
  });

  renderLikedJobs() {
    return this.props.likedJobs.map(job => {
      return (
        <Card>
          <View style={{ height: 200 }}>
            <View style={styles.detailWrapper}>
              <Text style={styles.italics}>{job.company}</Text>
              <Text style={styles.italics}>{job.post_date}</Text>
            </View>
          </View>
        </Card>
      );
    });
  }

  render() {
    return <ScrollView>{this.renderLikedJobs()}</ScrollView>;
  }
}

const styles = {
  detailWrapper: {
    marginBottom: 10,
    flexDirection: "row",
    justifyContent: "space-around"
  }
};

function mapStateToProps(state) {
  return { jobs: state.jobs };
}

export default connect(mapStateToProps)(ReviewScreen);

То же самое выше с this.props.likedJobs.map()

Ответы [ 2 ]

0 голосов
/ 30 мая 2019

Я закончил рефакторинг своего редуктора рабочих мест следующим образом:

export default function(state = INITIAL_STATE, action) {
  switch (action.type) {
    case FETCH_JOBS:
      const { listings } = action.payload;
      return { ...state, listing: listings.listing };
    default:
      return state;
  }
}
0 голосов
/ 13 мая 2019

Вместо вызова вашего API, в вашем создателе действий, Hardcore данные API и вернуть их.Если ваш редуктор продолжает возвращать неопределенное значение, ошибка в вашем коде.

Для асинхронных вызовов вам нужно использовать redux-thunk или redux-saga, я бы порекомендовал вам redux-saga, потому что он избегает ада обратного вызова.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...