11 Mistakes During Use React Native(翻译)

粗略的翻译自 11 mistakes I’ve made during React Native / Redux app development

一些可能会错误的评估

  1. 虽然有很多可以重复使用的组件,你还是需要分开考虑 iOS 和 Android 的布局。
  2. 当你评估表单实现的时候,应该要同时考虑表单的验证。开发 RN 比开发例如 Cordova 这样的 hybrid 的程序需要写的代码更多。
  3. 如果是基于一个已经有后端的 webapp 写代码,应该需要先去仔细看看后端提供的功能接口,因为你需要自己写逻辑,弄明白了 DB 结构数据关联,可以然你更好的规划你的 redux store。

尽量使用已有的组件

Google 一下就会发现,已经有大量的现成的组件,例如 buttons, footers 等。如果你没啥特殊要求,这些你都可以直接用。你要是有自己的特殊需要,也可以包装一下这些组件成你自己的,然后在里面自定义样式。不过你自己使用 View, Text, TouchableOpacity 等这些 RN 组件来自己包装对于你理解 RN 的工作原理。你自己打包的组件的版本也不会变,不像依赖外部模块。

不要分开搞 iOS 和 Android 的布局

如果你有不同的布局需求,那就分开。否则,你可以使用 RN Platform 提供的 API 来做一些小的区分。

如果布局很大不同,那就把布局内容放到不同的文件里面。

你可以使用 index.ios.js 给 iOS 布局用,index.android.js 给 Android 用。

共同的重复代码可以放到 helpers 里面。

错误的 redux store 规划

在规划你的 app 的时候可能会花很多时间在布局上,少量时间在数据规划上。这是个错误。redux 可以帮我们很好的处理数据。如果能规划好他,这会是一个很有用的工具,否则可能会带来不好的结果。

在我刚开始规划的时候,想着 reducers 是每个 container 的数据层。所以,如果有登录,忘记密码,Todo 列表页面,那应该来说会有各自的 reducers: SignIn, Forgot, ToDoList。

后来才发现,数据没那么好管理。我有 Todo 详情页,用这个方式规划的话,就需要有一个 ToDoDetails reducer。这是个巨大的失误。当用户在 Todo 列表页面选择了一项的时候,我们需要把数据传递给 ToDoDetails reducer。这表示需要额外的 actions 来发送数据给 reducer,这不太合理。

做了一些调查之后,打算该改结构

  1. Auth
  2. Todos
  3. Friends

Auth 用来存放 token。Todos 和 Friends reducers 用来存放实体数据,从名字就能理解。当从列表打开 ToDo 详情的时候,只需要根据 id 从 Todos 里面查询就可以了。

不管多复杂的结构,都推荐你这么搞,这样你总是知道你应该去哪里找你的数据。

错误的项目结构

对于新手来说,规划项目结构是个比较难的事情。

得看看你的项目是大项目?巨大的?还是小的。有多少 screen,20?30?还是 5 个,或者是只有个 Hello world?

一开始我的项目结构如下:

图不贴了,可以看原文。简单讲就是把 reducers actions 等分开放到不同的目录里面。

如果你的项目不大,例如 10 来个 screen 这么搞是挺好的。如果比较大,可以考虑下下面这个方式:

就是按照 screen 划分目录,把这个 screen 对应的 actions reducers 等放到一个目录下面。这样可以清楚的知道一个 container 和 action 等的关系。

如果你有通用的 style 文件,可以建一个 styles/index.js 文件。

还有很多其他的结构类型,你需要找到适合你自己的。

container 里面错误的结构

其实简单概括就是,应该尽量封装你的组件,比如 form 表单里面的东西,应该适当的做一些封装,比如搞一个 FormItem 这样的组件出来,就不用重复的写 Text 和 TextInput 的组合了。

但是也要注意,不要为了封装而封装,原文里面有个例子,把组件搞了一个 setTitle 方法,然后根据 id 来设置 title。作者的意思是,Dumb 组件不应该加入业务逻辑进来,比如加一个 id 就需要修改一下这个组件。

内联样式

就是这样的 <View style={{flex:1, flexDirection:'row', backgroundColor:'transparent'}}> ,慢慢会变得很难管理,也没法重用。应该一开始就把这个写入到单独的文件里面。

使用 redux 验证表单

这个是我犯的一个错误,但也有可能适合你们。

如果需要通过 redux 验证表单,我们需要创建 action, action type 和 reducer 里面单独的字段。这么做有点太麻烦了。

所以我们决定使用 state。不用 reducers, types 等。只用一些在 container 范围的简单的函数。这么做让我们删除了 action,reducer 文件里面不必要的函数。也不用处理维护 store,这么做很适合我们的项目。

大量依赖 zIndex

从 web 过来的人会比较喜欢 css 里面的 z-index,可以控制显示哪一层。但是在 RN 里面,一开始没有这个,但是后来也加上了。一开始用的时候挺好的,但是直到我开始在 Android 上面跑。。。现在我都是在构建的时候就考虑好他们将来展示的顺序。

不阅读依赖的模块的代码

简单说就是用第三方模块的时候,看文档是必须的了,但是有时候也需要看看代码的。比如不工作了,或者和文档描述不一致啥的。看代码也能学习到如何构建自己的模块。

使用 PanResonder 和 动画 API 的时候要小心

RN 提供了你构建完全 native 体验的 app 的能力。例如布局,手势,动画。

默认提供了布局功能,当你使用 View, Text, TextInput 这些 RN 模块的时候,手势和动画需要使用 PanResonder 和动画 API 来提供手势和动画。

一开始可能会觉得好难,什么时候开始,什么时候结束,长按,短按等。RN 也确实没有把这些讲的足够清晰。作者提供了一个例子

开始我们初始化一个 PanResonder 对象,针对我们感兴趣的 onPanResponderGrand(当用户点击 button 的时候调用) 和 onPanResponderRelease(当用户手指离开屏幕的时候调用) 设置了一些 handler。

同时我们也设置了 Animated 对象来帮我们处理动画。设置他的取值为 0,然后定义 _setOpacity 方法来改变 this.opacityAnimated 的值。在渲染之前,给 this.opacityAnimated 赋值为通常情况下的值。我们不使用 View,使用 Animated.View 来动态修改透明度。

可以看到,这没啥难理解的。当然你需要阅读这些 API 的文档让你的 app 更完美。希望这个例子可以让你有一个好的开始。

React Naive 很不错,你几乎可以用它做任何事情。如果有不行的,你还可以通过 Swift/Object C 或者 Java 来配合 RN 完成。此外还有一个大的社区。