Я работаю над приложением 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()