显示 React Native Redux Saga API 响应

Posted

技术标签:

【中文标题】显示 React Native Redux Saga API 响应【英文标题】:Display React Native Redux Saga API response 【发布时间】:2018-03-16 02:29:59 【问题描述】:

我已经与React Native 一起学习/工作了几个星期,我正在努力掌握如何与Redux 和Redux-Sagas 一起工作。我已经尝试了几天的研究,并且(认为)我已经掌握了它,但不幸的是我仍在挣扎。以下是我阅读并尝试过的一些资源:

https://shift.infinite.red/using-redux-saga-to-simplify-your-growing-react-native-codebase-2b8036f650de

https://hackernoon.com/moving-api-requests-to-redux-saga-21780f49cbc8

我正在使用Ignite-CLI 样板来创建一个应用程序来查询天气数据的 API。当使用来自apisauce 的常规api.get() 函数时,API 请求有效,但我无法让 Redux Saga 操作返回数据。我在想我只是不太了解这个概念。

这是我的 Api.js 文件,它使用 apisauce 从给定参数中获取 JSON 数据(效果很好)

/App/Services/Api.js

// a library to wrap and simplify api calls
import apisauce from 'apisauce'

// our "constructor"
const create = (baseURL = 'https://my-api-url.com/api/') => 

  const apiId = 'xxxxxxx'
  const apiKey = 'xxxxxxxxxxxxxxxxx'
  const resortKey = 'xxxxxx'
  const apiParams = resortKey + '?app_id=' + apiId + '&app_key=' + apiKey

  const api = apisauce.create(
    // base URL is read from the "constructor"
    baseURL,
    // here are some default headers
    headers: 
      'Cache-Control': 'no-cache'
    ,
    // 10 second timeout...
    timeout: 10000
  )

  const getReport = () => api.get(apiParams)

  return 
    getReport,
  


// let's return back our create method as the default.
export default 
  create

Ignite CLI 有一个很棒的生成器,可以自动生成 redux 操作和 sagas。以下是那些生成的文件:

/App/Redux/SnowReportRedux.js(Redux 操作)

import  createReducer, createActions  from 'reduxsauce'
import Immutable from 'seamless-immutable'

/* ------------- Types and Action Creators ------------- */

const  Types, Creators  = createActions(
  snowReportRequest: ['data'],
  snowReportSuccess: ['payload'],
  snowReportFailure: null
)

export const SnowReportTypes = Types
export default Creators

/* ------------- Initial State ------------- */

export const INITIAL_STATE = Immutable(
  data: null,
  fetching: null,
  payload: null,
  error: null
)

/* ------------- Reducers ------------- */

// request the data from an api
export const request = (state,  data ) =>
  state.merge( fetching: true, data, payload: null )

// successful api lookup
export const success = (state, action) => 
  const  payload  = action
  return state.merge( fetching: false, error: null, payload )


// Something went wrong somewhere.
export const failure = state =>
  state.merge( fetching: false, error: true, payload: null )

/* ------------- Hookup Reducers To Types ------------- */

export const reducer = createReducer(INITIAL_STATE, 
  [Types.SNOW_REPORT_REQUEST]: request,
  [Types.SNOW_REPORT_SUCCESS]: success,
  [Types.SNOW_REPORT_FAILURE]: failure
)

/App/Sagas/SnowReportSagas.js

import  call, put  from 'redux-saga/effects'
import SnowReportActions from '../Redux/SnowReportRedux'

export function * getSnowReport (api, action) 
  const  data  = action
  // make the call to the api
  const response = yield call(api.getReport, data)

  // success?
  if (response.ok) 
    yield put(SnowReportActions.snowReportSuccess(response.data))
   else 
    yield put(SnowReportActions.snowReportFailure())
  

然后,按照他们提供的示例,我将SnowReportRedux.js 中的SnowReportActionsSnowReportSagas.js 中的getSnowReport 函数添加到root saga 函数中:

//...imports & constants

export default function * root () 
  yield all([
    // some sagas only receive an action
    takeLatest(StartupTypes.STARTUP, startup),

    // some sagas receive extra parameters in addition to an action
    takeLatest(SnowReportTypes.SNOW_REPORT_REQUEST, getSnowReport, api)
  ])

这就是我感到困惑的地方;我如何在我的组件或屏幕中实际调用这些调度操作?我知道我必须import SnowReport Actions from '../Redux/SnowReportReduxmapDispatchToProps,但我无法让调度触发......这是我的一个屏幕上的一些片段:

/App/Containers/ResortReportScreen.js

//.. constructor

componentDidMount () 
  this.props.getSnowReport();


// .. render() / close component

const mapDispatchToProps = (dispatch) => 
  return 
    getSnowReport: () => dispatch( type: SnowReportActions.snowReportRequest() )
  


export default connect(null, mapDispatchToProps)(ResortReportScreen)

componentDidMount () 函数触发时,它应该dispatch SnowReportActions.snowReportRequest() 动作,对吧?每当我使用 console.log() 返回该操作的响应时,它最终都不会触发。我在这里做错了什么?使用actions时如何从我的API请求中获取数据以显示?

我的sagaMiddlewarereducers 都是由Ignite 自动生成的。如果有必要显示那些只是问。

【问题讨论】:

通过示例查看我的 repo here。 【参考方案1】:

函数SnowReportActions.snowReportRequest() 是一个动作创建者,它返回一个你必须调度的动作。你可以这样修复你的代码:

const mapDispatchToProps = (dispatch) => 
  return 
    getSnowReport: () => dispatch(SnowReportActions.snowReportRequest())
  

您甚至可以使用对象而不是 mapDispatchToProps (https://github.com/reactjs/react-redux/blob/master/docs/api.md) 的方法来简化代码

const mapDispatchToProps = 
    getSnowReport: SnowReportActions.snowReportRequest

【讨论】:

以上是关于显示 React Native Redux Saga API 响应的主要内容,如果未能解决你的问题,请参考以下文章

react-native 中的 Redux 错误

我无法在带有 redux 的 react-native 中使用地理定位

React-native + Redux(Combine Reducers):创建状态结构

使用 JWT Token、React Native 和 Redux 检索用户信息

如何在reducer中专门使用redux来获取react-native中的API?

错误:无法解析模块 react-redux/native