首页 > 解决方案 > react-navigation 和 api 调用的 Redux 错误

问题描述

我必须进行 api 调用并将数据状态保存在 redux

这就是我目前正在做的事情

import HomeScreen from './pages/home';

const mapStateToProps = (state) => ({
  isLoading: state.serviceReducer.isLoading,
  error: state.serviceReducer.error,
  data: state.serviceReducer.data
});

const mapDispatchToProps = (dispatch) => ({
  callService: () => dispatch(callWebservice())
})

export const callWebservice = () => {
  console.log("this is getting calles")
  return dispatch => {
    dispatch(serviceActionPending())
    console.log("COMING HERE?")
    fetch(`https://news119.herokuapp.com/getData`)
      .then(response => {
        console.log(response.data)
        dispatch(serviceActionSuccess(response.data))
      })
      .catch(error => {
        dispatch(serviceActionError(error))
      });
  }
}

export const serviceActionPending = () => ({
  type: ActionTypes.SERVICE_PENDING
})

export const serviceActionError = (error) => ({
  type: ActionTypes.SERVICE_ERROR,
  error: error
})

export const serviceActionSuccess = (data) => ({
  type: ActionTypes.SERVICE_SUCCESS,
  data: data
})

let ReduxAppContainer = connect(mapStateToProps, mapDispatchToProps)(HomeScreen);

这是我的反应导航 js

const AppNavigator = createStackNavigator({
    Home: {
      screen: ReduxAppContainer,
      key: "Home"
    },
    Details: {
      screen: DetailsScreen,
      header: {
        style: {
          backgroundColor: '#00cafe'
        }
      }
    },
    Intro: IntroScreen,
    Article: {
      screen: ExternalScreen,
      path: 'news/:id',
    },
    Settings: SettingsScreen,
    Bookmarks: BookmarksScreen,
    SingleBookmark: SingleBookmarkScreen

  }, {
    initialRouteName: "Home",
    headerMode: 'none',
    transitionConfig: (screen) => handleCustomTransition(screen),
  }
);

const AppContainer = createAppContainer(AppNavigator);

const AppNavigatorIntro = createStackNavigator({
    Home: {
      screen: ReduxAppContainer,
      key: "Home"
    },
    Details: {
      screen: DetailsScreen,
      style: {
        backgroundColor: '#00cafe'
      }
    },
    Intro: IntroScreen,
    Article: {
      screen: ExternalScreen,
      path: 'news/:id',
    },
    Settings: SettingsScreen,
    Bookmarks: BookmarksScreen,
    SingleBookmark: SingleBookmarkScreen

  }, {
    initialRouteName: "Intro",
    headerMode: 'none',
    transitionConfig: (screen) => handleCustomTransition(screen),
  }
);

const AppContainerIntro = createAppContainer(AppNavigatorIntro);

export {
  AppContainer,
  AppContainerIntro
};

ActionTypes.js

export const SERVICE_PENDING = 'service_pending'
export const SERVICE_ERROR = 'service_error'
export const SERVICE_SUCCESS = 'service_success'

ServiceReducer.js

import * as Actions from './ActionTypes'

const ServiceReducer = (state = {
  isLoading: false,
  error: undefined,
  data: {}
}, action) => {
  switch (action.type) {
    case Actions.SERVICE_PENDING:
      return Object.assign({}, state, {
        isLoading: true,
      });
    case Actions.SERVICE_ERROR:
      return Object.assign({}, state, {
        isLoading: false,
        error: action.error
      });
    case Actions.SERVICE_SUCCESS:
      return Object.assign({}, state, {
        isLoading: false,
        data: action.data
      });
    default:
      return state;
  }
}

export default ServiceReducer;

store.js

import {
  combineReducers,
  applyMiddleware,
  createStore,
  compose
} from 'redux';
import thunk from 'redux-thunk';
import {
  createLogger
} from 'redux-logger';

import serviceReducer from './ServiceReducer'

const AppReducers = combineReducers({
  serviceReducer,
});

const rootReducer = (state, action) => {
  return AppReducers(state, action);
}

const logger = createLogger();

let store = createStore(rootReducer, compose(applyMiddleware(thunk)));

export default store;

然后我像这样从主屏幕调用 callService

 componentDidMount() {
  this.props.callService()
}

componentWillReceiveProps(nextProps) {
  if (nextProps.data != null) {
    console.log('the state', nextProps)
    this.setState({
      dataSource: (nextProps.data)
    });
  }

  if (nextProps.error != undefined) {
    Alert.alert(
      'Error',
      nextProps.error,
      [{
        text: 'Do you want to reload',
        onPress: () => this.props.callService()
      }, ], {
        cancelable: false
      })
  }
}

但是当我记录这个“状态,nextProps”时,这就是我得到的

06-08 19:24:01.454 29384 32597 I ReactNativeJS: HEYYSYASYundefined
06-08 19:24:01.456 29384 32597 I ReactNativeJS: 0
06-08 19:24:01.458 29384 32597 I ReactNativeJS: undefined
06-08 19:24:01.559 29384 32597 I ReactNativeJS: this is getting calles
06-08 19:24:01.560 29384 32597 I ReactNativeJS: COMING HERE?
06-08 19:24:01.585 29384 32597 I ReactNativeJS: 'the state', { screenProps: undefined,
06-08 19:24:01.585 29384 32597 I ReactNativeJS:   navigation:
06-08 19:24:01.585 29384 32597 I ReactNativeJS:    { pop: [Function],
06-08 19:24:01.585 29384 32597 I ReactNativeJS:      popToTop: [Function],
06-08 19:24:01.585 29384 32597 I ReactNativeJS:      push: [Function],
06-08 19:24:01.585 29384 32597 I ReactNativeJS:      replace: [Function],
06-08 19:24:01.585 29384 32597 I ReactNativeJS:      reset: [Function],
06-08 19:24:01.585 29384 32597 I ReactNativeJS:      dismiss: [Function],
06-08 19:24:01.585 29384 32597 I ReactNativeJS:      goBack: [Function],
06-08 19:24:01.585 29384 32597 I ReactNativeJS:      navigate: [Function],
06-08 19:24:01.585 29384 32597 I ReactNativeJS:      setParams: [Function],
06-08 19:24:01.585 29384 32597 I ReactNativeJS:      state: { routeName: 'Home', key: 'id-1560002041272-1' },
06-08 19:24:01.585 29384 32597 I ReactNativeJS:      router: undefined,
06-08 19:24:01.585 29384 32597 I ReactNativeJS:      actions:
06-08 19:24:01.585 29384 32597 I ReactNativeJS:       { pop: [Function: pop],
06-08 19:24:01.585 29384 32597 I ReactNativeJS:         popToTop: [Function: popToTop],
06-08 19:24:01.585 29384 32597 I ReactNativeJS:         push: [Function: push],
06-08 19:24:01.585 29384 32597 I ReactNativeJS:         replace: [Function: replace],
06-08 19:24:01.585 29384 32597 I ReactNativeJS:         reset: [Function: reset],
06-08 19:24:01.585 29384 32597 I ReactNativeJS:         dismiss: [Function: dismiss],
06-08 19:24:01.585 29384 32597 I ReactNativeJS:         goBack: [Function: goBack],
06-08 19:24:01.585 29384 32597 I ReactNativeJS:         navigate: [Function: navigate],
06-08 19:24:01.585 29384 32597 I ReactNativeJS:         setParams: [Function: setParams] },
06-08 19:24:01.585 29384 32597 I ReactNativeJS:      getParam: [Function],
06-08 19:24:01.585 29384 32597 I ReactNativeJS:      getChildNavigation: [Function: getChildNavigation],
06-08 19:24:01.585 29384 32597 I ReactNativeJS:      isFocused: [Function: isFocused],
06-08 19:24:01.585 29384 32597 I ReactNativeJS:      isFirstRouteInParent: [Function: isFirstRouteInParent],
06-08 19:24:01.585 29384 32597 I ReactNativeJS:      dispatch: [Function],
06-08 19:24:01.585 29384 32597 I ReactNativeJS:      getScreenProps: [Function],
06-08 19:24:01.585 29384 32597 I ReactNativeJS:      dangerouslyGetParent: [Function],
06-08 19:24:01.585 29384 32597 I ReactNativeJS:      addListener: [Function: addListener],
06-08 19:24:01.585 29384 32597 I ReactNativeJS:      emit: [Function: emit] },
06-08 19:24:01.585 29384 32597 I ReactNativeJS:   isLoading: true,
06-08 19:24:01.585 29384 32597 I ReactNativeJS:   error: undefined,
06-08 19:24:01.585 29384 32597 I ReactNativeJS:   data: {},
06-08 19:24:01.585 29384 32597 I ReactNativeJS:   callService: [Function: callService] }

变量 dataSource 未定义。我确信 api 正在工作,因为如果我在没有 redux 的情况下执行此操作,它可以正常工作。我已经列出了 redux 中使用的所有代码。这是我第一次使用 redux,所以我不知道我做错了什么。

标签: react-nativereact-redux

解决方案


我认为问题出在fetch电话上。

fetch 方法返回一个 Response 对象,而不是直接将数据作为 JSON。

根据文档,您应该拥有:

fetch('https://news119.herokuapp.com/getData')
  .then(response => response.json())
  .then((responseJson) => {
    console.log(responseJson.data)
    dispatch(serviceActionSuccess(responseJson.data))
  })
  .catch((error) => {
    dispatch(serviceActionError(error))
  });

推荐阅读