React-Native配合ignite开发文档
1.部署调试
1)Nuclide的start package有时候有问题,手机显示奇怪的错误,可以在命令行
npm start -- --reset-cache
重置后,启动正常。
2)安装程序到真机,如果命令行不行,androidstudio里安装。
3)真机调试,弹出菜单,晃动手机出,如果不出,手机设置->程序->本程序->允许悬浮框。
模拟器,ctrl+m,调出调试菜单。
4)Nuclide菜单选择start debugging,然后手机调试菜单选择remote debug
然后在程序中打断点,单步执行,可以看出程序的流转路径。
Redux的程序有点类似QT和win32的消息泵,每个地方跳转不靠函数调用,全是异步消息,异步调用,声明消息的地方比较特殊Action,处理消息的地方也比较特殊,下面咱们着重过一下。
5)初步调试的时候,要解决程序编码问题,主要是多个逗号,函数名大小不一致,没有定义这些,因为js不需要编译,这些还只能运行时发现。
优先看手机的错误提示,因为手机屏幕较小,有时候外壳程序会直接崩溃,这时候可以在终端开npm start,看这个输出。
程序基本能运行起来,没有上面这种简单报错后,开始使用调试器查看程序变量进行正常的逻辑调试。
2.开发
Ignite汇集了多个主流开发库,并组装成自己的框架。咱们先对最常用的,从服务器请求数据开始,这个不同于android的处理,只需要”后台线程+网络请求”一步,React需要使用redux的方式:
构建Action -> reducer ->合并reducer -> sagas配置
调用路径是,screen里发起Action,通过上面的reducer配置,传递到Sagas处理,处理请求后,put Action回到Redux,改变state,然后state改变又回到screen里,对应到prop的改变,最终screen在componentWillReceiveProps收到请求的数据。
2.1 API请求
这个我理解的是:
1)所有同一个网站的API接口都要写到一个Service里
2)然后每个具体的接口函数都要封装成一组Redux+Saga,然后名字起名要和接口对应,这样可以最少的修改代码达到可用状态。
我们以仪表系统的请求为例:
假如服务器端提供2个接口函数:
1.get_equipment_name_list GET无参
2.get_equipment_model_list POST参数是nameId
我们现在开始做第一个接口。
1.第一步,写Service
import apisauce from 'apisauce'
// our "constructor"
const create = (baseURL ='http://equipment.jimglobal.com/api/') => {
// ------
// STEP 1
// ------
//
// Create and configure an apisauce-based api object.
//
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 login=(username,password) => api.post('login',{username :username,password:password})
const get_equipment_name_list=() => api.get('get_equipment_name_list')
const get_equipment_model_list=(nameId) => api.post('get_equipment_model_list', {nameId:nameId})
return {
login,
get_equipment_name_list,
get_equipment_model_list
}
}
// let's return back our create method as the default.
export default {
create
}
要点:1) baseURL写服务器地址
2)绿色的部分,注意get, post,和参数的处理。
3)红色的部分,对外提供的接口。
这个怎么上传文件我还没试。这个一般都不会写错。
2.第二步,写redux
对于get_equipment_name_list和get_equipment_model_list,我们要提供独立的redux。
比如我们第一个接口我们叫GetEquipmentNameList,我们就可以做下面
使用ignite generate redux GetEquipmentNameList
生成的代码:
我们不需要参数,所以可以把data去掉,改为:
const { Types, Creators } = createActions({
getEquipmentNameListRequest: null,
getEquipmentNameListSuccess: ['payload'],
getEquipmentNameListFailure: null
})
INITIAL_STATE中也不需要data,所以可以去掉
export const INITIAL_STATE = Immutable({
fetching: null,
payload: null,
error: null
})
Request自然也不需要data,去掉
// request the data from an api
export const request = (state) =>
state.merge({ fetching: true, payload: null })
然后这个文件就改好了,可以看到我们只需要调整参数部分,,和state部分,其他的用默认的就可以。
但是具体原理也要明白:
createActions中的getEquipmentNameListRequest被自动转化为GET_EQUIPMENT_NAME_LIST_REQUEST, 最后createReducer和处理函数关联起来,处理函数更新state。
3.第三步,写saga
Saga是真实发起api请求的地方。
默认生成的代码
我们注意到getGet#,生成器会添加get,所以咱们的命名还是不要GET这种动词比较好。除了默认的data参数,其他都是好的,所以命令很重要,配套的Redux和Sagas命令一定要一样。我们把action和data去掉,这个就完了。
export function * getGetEquipmentNameList (api) {
// make the call to the api
const response = yield call(api.getgetEquipmentNameList)
4.第四步,连接
连接要分两个地方,redux和saga要分别做连接
打开Redux/index.js文件:
EquipmentNameList : require('./GetEquipmentNameListRedux').reducer
这一行是我们要添加的,注意这个EquipmentNameList,这个不是胡乱起的,在screen中的mapStateToProps中的state是全局的,EquipmentNameList就是我们这个redux的数据。
打开Sagas/index.js文件,跟着注释家,导入types,导入saga的函数
/* ------------- Types ------------- */
import { GetEquipmentNameListTypes } from '../Redux/GetEquipmentNameListRedux'
/* ------------- Sagas ------------- */
import { getGetEquipmentNameList} from './GetEquipmentNameListSagas'
如果api是新的,就要搞一个实例
const appApi=AppApi.create()
然后连入root
takeLatest(GetEquipmentNameListTypes.GET_EQUIPMENT_NAME_LIST_REQUEST, getGetEquipmentNameList, appApi),
连接就做完了。
按步骤做,1分钟左右就能完成一套。
5.第五步,Screen里使用
现在我们在LoginScreen里加入对这个接口的调用。
先导入Action
import GetEquipmentNameListActions from '../Redux/GetEquipmentNameListRedux'
然后处理mapStateToProps,把数据合并到state去。
const mapStateToProps = (state) => {
return {
fetching: state.login.fetching,
response: state.login.response,
error: state.login.error,
equipmentname_payload : state.EquipmentNameList.payload
}
}
然后处理mapDispatchToProps,把Action封装成自己的props“getEquipmentNameList”, 这样自己的函数中就可以直接调用了。
const mapDispatchToProps = (dispatch) => {
return {
attemptLogin: (username, password) => dispatch(LoginActions.loginRequest(username, password)),
getEquipmentNameList:() => dispatch(GetEquipmentNameListActions.getEquipmentNameListRequest())
}
}
调用:随便什么地方,只要调用,就会发起请求。
//在这个地方做EquipmentName
this.props.getEquipmentNameList();
最后,接收请求,这个equipmentname_payload就是mapStateToProps最下面那行的那个,下面自己想怎么做就怎么做了。
componentWillReceiveProps (newProps) {
// this.forceUpdate()
// Did the login attempt complete?
if(newProps.equipmentname_payload)
{
}
作者:MackJson
链接:http://www.jianshu.com/p/efc9a00b843a
來源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
网友评论