我有一个用redux实现的react-native项目,我试图使用fetch从api中获取数据。我无法从api获取数据。此外,它没有给出任何错误。我的代码如下所示:
Action.js
//import axios from 'axios';
export const FETCH_DATA = 'fetch_data';
export const FETCH_SUCCESS = 'fetch_success';
export function fetchData() {
return dispatch => {
return(fetch('https://api.myjson.com/bins/fz62x'))
.then(res => res.json())
.then(data => {
dispatch({
type: FETCH_DATA,
payload: data
})
}
)
}
}
我有2个reducer文件:
fetch_data.js
import FETCH_DATA from '../actions'
const initialState = {
result:[],
isFetching: false,
error: false
}
export default function fetchReducer(state = initialState, action) {
switch (action.type) {
case FETCH_DATA: {
return {
...state,
isFetching: true,
result: action.payload.data
}
}
default:
return state
}
}
index.js
import { combineReducers } from 'redux';
import fetchData from './fetch_data';
const rootReducer = combineReducers({
result: fetchData
})
export default rootReducer;
我正在尝试访问从api获取的数据的组件:
HomeScreen.js
import React from 'react';
import { StyleSheet,
Text,
View,
ActivityIndicator
} from 'react-native';
import { bindActionCreators } from 'redux';
import reducer from '../reducers/fetch_data';
import thunk from 'redux-thunk';
import { connect } from 'react-redux';
import { fetchData } from '../actions';
class HomeScreen extends React.Component {
static navigationOptions = {
header: null
}
componentDidMount() {
this.props.fetchData()
}
render() {
const { result, isFetching } = this.props.result;
if (isFetching) {
return(
<View style={{flex: 1, flexDirection: 'column', alignItems: 'center', justifyContent: 'center'}}>
<ActivityIndicator size={'large'} />
</View>
)
} else {
return(
<View style={{flex: 1, flexDirection: 'column', alignItems: 'center', justifyContent: 'center'}}>
<Text>{result.length}</Text>
</View>
)
}
}
}
function mapStateToProps(state) {
return {
result: state.result
}
}
function mapDispatchToProps(dispatch) {
return {
...bindActionCreators({ fetchData }, dispatch)
}
}
export default connect(mapStateToProps, mapDispatchToProps)(HomeScreen);
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
backgroundColor: 'blue'
},
welcome: {
color: '#FFF',
fontSize: 30
}
})
所以,在我的Homescreen.js中,我尝试在<Text>{result}</Text>
中查看api的结果,我得到一个空白页面。如果我试图得到结果道具的长度,我得到0.这个代码有什么问题,有人可以帮我这个吗?
注意:此外,isFetching
道具正在返回默认值,即。是的,所以我直接导航到提到结果道具的另一页。
编辑1 动作,减速器和组件的更新文件如下:
Actions.js
//import axios from 'axios';
//import { FETCH_DATA, FETCH_DATA_SUCCESS, FETCH_DATA_FAILURE } from '/constants';
export const FETCH_DATA = 'FETCH_DATA';
export const FETCH_DATA_SUCCESS = 'FETCH_DATA_SUCCESS';
export const FETCH_DATA_FAILURE = 'FETCH_DATA_FAILURE';
export function fetchData() {
return (dispatch) => {
dispatch(getData())
fetch('https://api.myjson.com/bins/fz62x')
.then(res => res.json())
.then(json => dispatch(getDataSuccess(json.results)))
.catch(err => dispatch(getDataFailure(err)))
}
}
function getData() {
return {
type: FETCH_DATA
}
}
function getDataSuccess(data) {
return {
type: FETCH_DATA_SUCCESS,
data
}
}
function getDataFailure() {
return {
type: FETCH_DATA_FAILURE,
}
}
fetch_data.js
import FETCH_DATA from '../actions';
import FETCH_DATA_SUCCESS from '../actions';
import FETCH_DATA_FAILURE from '../actions';
const initialState = {
result_array:[],
isFetching: false,
error: false
}
export default function fetchReducer(state = initialState, action) {
switch (action.type) {
case FETCH_DATA: {
return {
...state,
isFetching: true,
}
}
case FETCH_DATA_SUCCESS: {
return {
...state,
isFetching: false,
result_array: action.payload
}
}
case FETCH_DATA_FAILURE:
return {
...state,
isFetching: false,
error:true
}
default:
return state
}
}
HomeScreen.js
import React from 'react';
import { StyleSheet,
Text,
View,
ActivityIndicator
} from 'react-native';
import { bindActionCreators } from 'redux';
import reducer from '../reducers/fetch_data';
import thunk from 'redux-thunk';
import { connect } from 'react-redux';
import { fetchData } from '../actions';
class HomeScreen extends React.Component {
static navigationOptions = {
header: null
}
componentDidMount() {
this.props.fetchData()
}
render() {
const { result, isFetching } = this.props.result;
if (isFetching) {
return(
<View style={{flex: 1, flexDirection: 'column', alignItems: 'center', justifyContent: 'center'}}>
<ActivityIndicator size={'large'} />
</View>
)
} else {
return(
<View style={{flex: 1, flexDirection: 'column', alignItems: 'center', justifyContent: 'center'}}>
<Text>{result}</Text>
</View>
)
}
}
}
function mapStateToProps(state) {
return {
result_array: state.result.result_array
}
}
function mapDispatchToProps(dispatch) {
return {
...bindActionCreators({ fetchData }, dispatch)
}
}
export default connect(mapStateToProps, mapDispatchToProps)(HomeScreen);
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
backgroundColor: 'blue'
},
welcome: {
color: '#FFF',
fontSize: 30
}
})
答案 0 :(得分:1)
我不确定你的问题,但希望能有所帮助。
首先,您的Action.js
,您使用数组调度有效负载:
dispatch({
type: FETCH_DATA,
payload: data
})
data
是数组
[
{ createdOn: '', taskList: [{}, {}, ...] },
{ createdOn: '', taskList: [{}, {}, ...] },
...
]
在您的fetch_data.js
中,您收到了有阵列的有效负载,但是访问.data
它将未定义,您必须更改为result: action.payload
return {
...state,
isFetching: true,
result: action.payload.data // <-- undefined
}
但我认为您应该使用FETCH_DATA
类型返回{ isFetching: true }
而FETCH_SUCCESS
返回{ isFetching: false, result: action.payload
这样
// action.js
fetchData() {
dispatch({
type: FETCH_DATA
})
return fetch('https://api.myjson.com/bins/fz62x')
.then(res => res.json())
.then(data => {
dispatch({
type: FETCH_SUCCESS,
payload: data
})
})
}
// fetch_data.js
switch (action.type) {
case FETCH_DATA: {
return {
...state,
isFetching: true
}
}
case FETCH_SUCCESS: {
return {
...state,
isFetching: false,
result: action.payload
}
}
}
但看起来有点奇怪,因为你在使用时得到0得到结果的长度,它应该是undefined
,除非它返回result
为空数组的状态的defaultValue
答案 1 :(得分:1)
您需要解决一些问题。如果你将代码上传到github或codesandbox会更好,那么我们可以更容易地理解代码结构。
首先,return (fetch('url')).then
或return fetch(url).then
,它们都按预期工作,但您应该记住,redux-thunk
并不关心您的回报价值,这个承诺无关,这没关系,它不需要做任何事情。
让我们先在fetch_data.js
修复语法错误:
import FETCH_DATA from '../actions'
应该是:
import { FETCH_DATA } from '../actions' // I don't know why didn't your build tool report an error here.
根据您的目的,我认为您也应该在这里导入FETCH_SUCCESS
。
然后我们可以谈谈你的行动和减速器流程:
return(fetch('https://api.myjson.com/bins/fz62x'))
.then(res => res.json())
.then(data => {
dispatch({
type: FETCH_DATA,
payload: data
})
}
)
}
和reducer:
switch (action.type) {
case FETCH_DATA: {
return {
...state,
isFetching: true,
result: action.payload.data
}
}
default:
return state
}
你只处理FETCH_DATA
(我认为你可能应该在这里使用FETCH_SUCCESS
),另一种行动类型也应该是派遣和解析。
我会建议这样的流程:
Action.js
:
export const FETCH_DATA = "fetch_data";
export const FETCH_SUCCESS = "fetch_success";
export function fetchData() {
return dispatch => {
fetch("https://api.myjson.com/bins/fz62x")
.then(res => res.json())
.then(data => {
dispatch({
type: FETCH_SUCCESS,
payload: data
});
});
dispatch({
type: FETCH_DATA
});
};
}
通过此操作,您现在可以调度FETCH_DATA
告诉应用程序您首先开始获取数据,并在获取成功时调度FETCH_SUCCESS
。
fetch_data.js
:
import { FETCH_DATA, FETCH_SUCCESS } from "./actions";
const initialState = {
result: [],
isFetching: false,
error: false
};
export default function fetchReducer(state = initialState, action) {
switch (action.type) {
case FETCH_DATA: {
return {
...state,
isFetching: true,
error: false
};
}
case FETCH_SUCCESS: {
return {
result: action.payload, // The action.payload.data isn't what you want
isFetching: false,
error: false
};
}
default:
return state;
}
}
现在,您的reducer将使用FETCH_DATA
和FETCH_SUCCESS
另一件事是我不知道你为什么要输入thunk和reducer
Homescreen.js
,如果您不打算在那里创建redux商店,那就不应该存在(我假设您<Provider store={store}>{...your application}</Provider>
上有Homescreen
答案 2 :(得分:1)
您必须拥有50条评论声誉
很抱歉,但我刚看到你的编辑1出了问题。我是对的
case FETCH_DATA_SUCCESS: {
return {
...state,
isFetching: false,
result_array: action.payload <-- this is undefined. it should be action.data from your action
}
}