无法使用fetch()

时间:2018-01-10 03:24:41

标签: javascript react-native redux

我有一个用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
  }
})

3 个答案:

答案 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')).thenreturn 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_DATAFETCH_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
    }
  }