简体   繁体   English

无法使用fetch()从api获取数据

[英]Unable to fetch data from api using fetch()

I have a react-native project implemented with redux where I am trying to fetch data from an api using fetch.I am unable to fetch the data from the api.Also,it doesn't give any errors. 我有一个用redux实现的react-native项目,我试图使用fetch从api中获取数据。我无法从api获取数据。此外,它不会给出任何错误。 My code is as shown below: 我的代码如下所示:

Action.js 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
          })
          }
        )
    }
}

I have 2 reducer files: 我有2个reducer文件:

fetch_data.js 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 index.js

import { combineReducers } from 'redux';
import  fetchData  from './fetch_data';

const rootReducer = combineReducers({
  result: fetchData
})

export default rootReducer;

My component where I am trying to access the data fetched from the api: 我试图访问从api获取的数据的组件:

HomeScreen.js 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
  }
})

So,in my Homescreen.js where I try to ge the result of the api in <Text>{result}</Text> ,I get a blank page. 所以,在我的Homescreen.js中,我尝试在<Text>{result}</Text> api的<Text>{result}</Text> ,我得到一个空白页面。 If I try to get the length of the result props,I get 0.What is the issue with this code,can anyone please help me with this? 如果我试图得到结果道具的长度,我得到0.这个代码的问题是什么,有人可以帮我这个吗?

NOTE: Also, isFetching props is returning the default value,ie false, so I am directly navigated to the other page where result prop is mentioned. 注意:另外, isFetching props返回默认值,即false,因此我直接导航到提到结果prop的其他页面。

EDIT 1 Updated files for the action,reducer and component are given below: 编辑1动作,减速器和组件的更新文件如下:

Actions.js 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 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 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
  }
})

I'm not sure about your problem but hope this help. 我不确定你的问题,但希望这有帮助。

First, Your Action.js , you dispatch payload with array: 首先,您的Action.js ,您使用数组调度有效负载:

dispatch({
  type: FETCH_DATA,
  payload: data
})

that data is array 那个data是数组

[
  { createdOn: '', taskList: [{}, {}, ...] },
  { createdOn: '', taskList: [{}, {}, ...] },
  ...
]

In your fetch_data.js You received payload with array but access .data it will got undefined, you have to change to result: action.payload 在你的fetch_data.js你收到了带数组的有效负载,但访问.data它将被定义为未定义,你必须改为result: action.payload

return {
  ...state,
  isFetching: true,
  result: action.payload.data // <-- undefined
}

but I think you should have type FETCH_DATA to return { isFetching: true } and FETCH_SUCCESS return { isFetching: false, result: action.payload like this 但我认为你应该有类型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
    }
  }
}

but It looks a bit weird because you got 0 when use get the length of result, it should be undefined unless it return defaultValue of state that result is empty array 但它看起来有点奇怪,因为你在使用获得结果的长度时得到0,它应该是undefined除非它返回defaultValue状态, result是空数组

There are a few things you need to fix. 您需要解决一些问题。 It would be better if you upload the codes to github or codesandbox then we can understand you code structure easier. 如果你将代码上传到github或codesandbox会更好,那么我们可以更容易地理解你的代码结构。

First of all, return (fetch('url')).then or return fetch(url).then , both of them work as you expect, but you should keep in mind that the redux-thunk doesn't care about you return value, this promise has nothing to do, that's alright, it doesn't need to do anything. 首先, return (fetch('url')).thenreturn fetch(url).then return (fetch('url')).then ,它们都按预期工作,但你应该记住, redux-thunk并不关心你的回归价值,这个承诺无关,没关系,它不需要做任何事情。

Let's fix your syntax error in fetch_data.js first: 让我们先修复fetch_data.js的语法错误:

import FETCH_DATA from '../actions'

should be : 应该 :

import { FETCH_DATA } from '../actions' // I don't know why didn't your build tool report an error here.

According to your purpose, I think you should import the FETCH_SUCCESS here as well. 根据您的目的,我认为您也应该在这里导入FETCH_SUCCESS

Then we can talk about your action and reducer flow : 然后我们可以谈谈你的行动和减速器流程:

return(fetch('https://api.myjson.com/bins/fz62x'))
   .then(res => res.json())
      .then(data => {
      dispatch({
        type: FETCH_DATA,
        payload: data
      })
      }
    )
}

and reducer : 和减速机:

switch (action.type) {
  case FETCH_DATA: {
    return {
      ...state,
      isFetching: true,
      result: action.payload.data
    }
  }

  default:
    return state
}

You only deal with FETCH_DATA (and I think you probably should use FETCH_SUCCESS here), another action type should be dispatch and parse as well. 你只处理FETCH_DATA (我想你可能应该在这里使用FETCH_SUCCESS ),另一个动作类型也应该是dispatch和parse。

I will suggest the flow like this : 我会建议这样的流程:

Action.js : 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
    });
  };
}

With this you now dispatch FETCH_DATA to tell the application you start to fetch data first, and dispatch FETCH_SUCCESS when fetch succeed. 有了这个,你现在调度FETCH_DATA告诉应用程序你首先开始获取数据,并在获取成功时调度FETCH_SUCCESS

And the fetch_data.js : 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;
  }
}

And now your reducer will respond correctly with FETCH_DATA and FETCH_SUCCESS 现在,您的reducer将使用FETCH_DATAFETCH_SUCCESS正确响应

And another thing is I don't know why you import thunk and reducer in your Homescreen.js , it should not be there if you are not going to create you redux store there (I assume that you have a <Provider store={store}>{...your application}</Provider> upon the Homescreen which you should have) 另一件事是我不知道为什么你在Homescreen.js导入thunk和reducer,如果你不打算在那里创建你的redux存储,它应该不存在(我假设你有一个<Provider store={store}>{...your application}</Provider>您应该拥有的主Homescreen上的<Provider store={store}>{...your application}</Provider>

You must have 50 reputation to comment 你必须有50个评论的声誉

Sorry, but i just seen that your edit 1 has something wrong. 对不起,但我刚看到你的编辑1出了问题。 iam i right 我是对的

case FETCH_DATA_SUCCESS: {
    return {
      ...state,
      isFetching: false,
      result_array: action.payload <-- this is undefined. it should be action.data from your action
    }
  }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM