千家信息网

使用React Native/Redux开发中会遇到什么错误

发表于:2026-11-03 作者:千家信息网编辑
千家信息网最后更新 2026年11月03日,这篇文章主要为大家展示了"使用React Native/Redux开发中会遇到什么错误",内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下"使用React Nat
千家信息网最后更新 2026年11月03日使用React Native/Redux开发中会遇到什么错误

这篇文章主要为大家展示了"使用React Native/Redux开发中会遇到什么错误",内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下"使用React Native/Redux开发中会遇到什么错误"这篇文章吧。

1.错误的估计

有可能你对***个React Native(RN)应用程序的预估是完全错误的!

  • 1)你需要分别考虑iOS和Android版本的布局!在布局的时候,有很多组件可以重复使用;如果ios和Android的页面结构不同,就需要对他们分开单独布局。

  • 2)对form进行评估时,***也考虑一下数据层验证。

  • 3)了解数据库结构,有助于正确地规划redux

2.尽量使用基础组件(buttons,footers,headers,inputs,texts)

google搜索RN的基础组件,你会发现有很多现有组件可以方便的用到项目中,如buttons,footers等。如果项目中没有特别的布局设计,只需要使用这些基础组件就可以构建一个页面。如果有一些特殊的设计,例如,特殊的button样式,你就需要为每个按钮设置自定义样式。你可以封装已经构建好的组件,并为它们定制样式。但是我觉得使用View,Text,TouchableOpacity和RN的其他组件来构建自己的组件更加有意义。因为你会有更多的rn实践,并且深刻理解如何使用RN。最重要的一点,你可以确定你自己构建的组件版本不会被改变。

3.不要把iOS和Android的布局分开

如果iOS和Android布局大致一样,只有一小部分不同,你可以简单地使用RN提供的Platform API根据设备平台进行区分。

如果布局完全不同 – ***分散在不同的文件中单独布局。

如果你给一个文件命名为index.ios.js – 程序打包时,在iOS中将使用这个文件显示iOS布局。 index.android.js也是一样的道理。

你可能会问:"代码怎么复用呢?" 你可以将重复的代码移动到助手函数中。需要的时候只复用这些助手函数。

4.错误的redux store规划。

初学者经常会犯的一个很大的错误就是,当你在规划你的应用程序时,你可能会考虑很多布局相关的问题,却很少考虑关于数据的处理。

Redux能够帮助我们正确地存储数据。如果redux规划的好 – 它将是管理应用程序数据的强大工具。

当我刚刚开始构建RN应用程序时,我曾考虑将reducers作为每个container的数据存储。所以,如果你有登录,忘记密码,待办事项列表页面 – 使用他们的缩写比较简单:SignIn, Forgot, ToDoList.

在进行了一段工作后,我发现管理数据没有想象中的容易。

当我从ToDo列表中选择项目时 – 我需要将数据传递给ToDoDetails reducer。这意味着使用了额外的操作来发送数据到reducer。

在做了一些调查之后,我决定以不同的方式规划结构。一个例子:

  1. 鸿蒙官方战略合作共建--HarmonyOS技术社区

  2. Auth

  3. Todos

  4. Friends

Auth用于存储认证的token。

而ToDos和Friends reducers用于存储实体,当我去ToDo Detail页面时 – 我只需要通过ID搜索所有的ToDos。

对于更复杂的结构,我推荐使用这种规划,你可以快速的定位到你想找到的。

5.错误的项目结构

作为初学者时,总是规划不好项目结构。

首先 ,需要分析你的项目是不是足够大?

你的应用程序中有多少个页面? 20?30?10?5?还是只有一个"Hello World"页面?

我遇到并开始实施的***个结构是这样的:

如果你的项目不超过10个页面,使用上面这种结构是没有问题的。但是如果项目特别大 – 你可以考虑这样规划结构:

区别在于,***种类型建议我们将actions和reducers与container分开存储。第二种- 把它们存储在一起。如果应用程序很小 – 将redux模块从container中分离出来会更加有用。

如果你有通用的样式(如Header、Footer、Buttons) – 你可以单***建一个名为"styles"的文件夹,在那里设置一个index.js文件并在其中写入通用样式。然后在每个页面上重复使用它们。

实际项目中会有很多不同的结构。你应该了解使用哪种结构更适合你的需求。

6.错误的container结构。没有从一开始就使用smart/dumb组件

当你开始使用RN并初始化项目时,index.ios.js文件中已经有一些代码,存储在一个单独的对象中。

在实际开发项目中,你将需要使用很多组件,不仅仅是由RN提供的,还有自己构建的一些组件。构建container时,可以重用它们。

考虑该组件:

import React, { Component } from ‘react’; import {    Text,    TextInput,    View,    TouchableOpacity } from ‘react-native’; import styles from ‘./styles.ios’;  export default class SomeContainer extends Component {    constructor(props){        super(props);               this.state = {            username:null        }    }    _usernameChanged(event){               this.setState({            username:event.nativeEvent.text        });     }    _submit(){               if(this.state.username){                       console.log(`Hello, ${this.state.username}!`);        }               else{                       console.log(‘Please, enter username’);        }     }                     render() {               return (                                                                                                                                                                      Username                                                                                                                                                                        Submit                                                                                              );     } }

所有样式都存储在一个单独的模块中。

包裹在TouchableOpacity中的button组件应该单独分离出来,这样才能方便我们以后重复使用它。Image组件,以后也可能重复使用,所以也应该把它分离出来。

做了一些改变之后的样子:

import React, { Component, PropTypes } from 'react'; import {     Text,     TextInput,     View,     TouchableOpacity } from 'react-native'; import styles from './styles.ios';  class Avatar extends Component{     constructor(props){         super(props);     }     render(){                 if(this.props.imgSrc){                         return(                                                                                     )          }          return null;     } } Avatar.propTypes = {     imgSrc: PropTypes.object }  class FormItem extends Component{     constructor(props){         super(props);     }     render(){         let title = this.props.title;         return(                                                    {title}                                                                      )     } } FormItem.propTypes = {     title: PropTypes.string,     value: PropTypes.string,     onChange: PropTypes.func.isRequired }  class Button extends Component{     constructor(props){         super(props);     }     render(){         let title = this.props.title;         return(                                                                                        {title}                                                                                )     } }              Button.propTypes = {     title: PropTypes.string,     onPress: PropTypes.func.isRequired } export default class SomeContainer extends Component {     constructor(props){         super(props);         this.state = {             username:null         }     }     _usernameChanged(event){         this.setState({             username:event.nativeEvent.text          });     }     _submit(){         if(this.state.username){             console.log(`Hello, ${this.state.username}!`);         }         else{             console.log('Please, enter username');         }     }     render() {         return (                                                                                                                                   

现在的代码看起来更多了 – 因为我们为Avatar,FormItem和Button组件添加了包装器,但现在我们可以在需要的地方重复使用这些组件。我们可以将这些组件移动到单独的模块中,并导入我们需要的任何地方。我们也可以添加其他一些Props,例如style,TextStyle,onLongPress,onBlur,onFocus。而且这些组件是完全可以定制的。

注意,一定不要深度定制一个小组件, 这样会使组件过于繁琐,代码会变的很难阅读。即使现在添加新属性的想法看起来像是解决任务的最简单的方法,将来这个小小的属性在阅读代码时可能会引起困惑。

关于理想的smart/dumb组件,看一下这个:

class Button extends Component{     constructor(props){         super(props);     }     _setTitle(){                 const { id } = this.props;                 switch(id){                         case 0:                                 return 'Submit';                         case 1:                                 return 'Draft';                         case 2:                                 return 'Delete';                         default:                                 return 'Submit';          }     }                      render(){                    let title = this._setTitle();                      return(                                                                                        {title}                                                                              )     } } Button.propTypes = {     id: PropTypes.number,     onPress: PropTypes.func.isRequired } export default class SomeContainer extends Component {     constructor(props){         super(props);         this.state = {             username:null         }     }     _submit(){         if(this.state.username){             console.log(`Hello, ${this.state.username}!`);         }         else{             console.log('Please, enter username');         }     }     render() {         return (                                          

我们已经"升级"了Button组件。用一个叫做"id"的新属性来替换属性"title"。现在Button组件就变的"灵活"了。传0 – button组件会显示"submit"。传2 – 显示"delete"。但这可能会有一些问题。

Button被创建为一个dumb组件 – 只是为了显示数据,传递数据这件事由它的更高一级的组件来完成。

如果我们将5作为id传递给这个组件,我们就需要更新组件,以便让它适应这个改动。dumb组件,就是细分的小组件,它只要接收props就好了,如果有state也应该与全局的无关。

7.行内样式

在使用RN布局之后,我遇到了行内样式的写作风格问题。类似这样:

render() {         return (                              

当你这样写的时候,你会想:"暂时这样写,等我在模拟器中运行之后 – 如果布局没问题,再把样式移动到单独的模块。"也许这是一个好的想法。但是..不幸的是,你往往会选择性忽略行内样式…

一定要在独立的模块中编写样式,远离行内样式。

8.使用redux验证表单

要使用redux来验证表单,我需要在reducer中创建action,actionType单独的字段,这样做很麻烦。

所以我决定只借助state来完成验证。没有reducers,types等等,只是在container级别上的纯功能函数。从action和reducer文件中删除不必要的函数,这个策略对我帮助很大。

9.过于依赖zIndex

很多人从web开发转到RN开发。在web中有一个css属性z-index,它可以帮助我们在需要的层级显示我们想要的内容。

在RN中,一开始没有这样的特性。但后来又被添加进来了。起初,使用起来还挺简单的。只需为元素设置zIndex属性,它就会按照任何你想要的图层顺序来渲染。但是在Android上测试之后…现在我只用zIndex来设置展示层的结构。

10.不仔细阅读外部组件的源码

你可以引入外部组件来节省你的开发时间。

但有时这个模块可能会中断,或者不像描述的那样工作。阅读源码你才会明白哪里出现了错误。也许这个模块本身就有问题,或者你只是用错了。另外 – 如果你仔细阅读其他模块的源码,你将会学习到如何构建自己的组件。

11.要小心手势操作和Animated API。

RN为我们提供了构建完全原生应用程序的能力。怎么让用户感觉是原生应用?页面布局,滑动手势,还是展示动画?

当你使用View,Text,TextInput和其他RN提供的默认模块时,手势和动画应该由PanResponder和Animated API来处理。

如果你是从web转过来的rn开发工程师,获取用户的手势操作可能会有些困难,你需要区分什么时候开始,什么时候结束,长按,短按。你可能还不够清楚怎么在RN中模拟这些动画操作。

这是我用PanResponder和Animated建立的Button组件。这个button是为了捕捉用户手势而构建的。例如 – 用户按下项目,然后将手指拖到一边。在按下按钮时,借助于动画API,构建button按压下的不透明度的变化:

'use strict'; import React, { Component, PropTypes } from 'react'; import { Animated, View, PanResponder, Easing } from 'react-native'; import moment from 'moment'; export default class Button extends Component {     constructor(props){         super(props);                         this.state = {             timestamp: 0         };                 this.opacityAnimated = new Animated.Value(0);                         this.panResponder = PanResponder.create({    onMoveShouldSetPanResponderCapture: (evt, gestureState) => true,    onStartShouldSetResponder:() => true,    onStartShouldSetPanResponder : () => true,    onMoveShouldSetPanResponder:(evt, gestureState) => true,    onPanResponderMove: (e, gesture) => {},     onPanResponderGrant: (evt, gestureState) => {            /**THIS EVENT IS CALLED WHEN WE PRESS THE BUTTON**/        this._setOpacity(1);               this.setState({            timestamp: moment()        });               this.long_press_timeout = setTimeout(() => {                        this.props.onLongPress();        }, 1000);    },    onPanResponderStart: (e, gestureState) => {},    onPanResponderEnd: (e, gestureState) => {},    onPanResponderTerminationRequest: (evt, gestureState) => true,    onPanResponderRelease: (e, gesture) => {           /**THIS EVENT IS CALLED WHEN WE RELEASE THE BUTTON**/        let diff = moment().diff(moment(this.state.timestamp));               if(diff < 1000){                       this.props.onPress();        }        clearTimeout(this.long_press_timeout);               this._setOpacity(0);               this.props.releaseBtn(gesture);    }      });     }     _setOpacity(value){          /**SETS OPACITY OF THE BUTTON**/         Animated.timing(                 this.opacityAnimated,         {             toValue: value,             duration: 80,         }         ).start();     }              render(){                 let longPressHandler = this.props.onLongPress,             pressHandler = this.props.onPress,             image = this.props.image,             opacity = this.opacityAnimated.interpolate({               inputRange: [0, 1],               outputRange: [1, 0.5]             });                          return(                                                               {image}                                                      )     } } Button.propTypes = {     onLongPress: PropTypes.func,     onPressOut: PropTypes.func,     onPress: PropTypes.func,     style: PropTypes.object,     image: PropTypes.object }; Button.defaultProps = {     onPressOut: ()=>{ console.log('onPressOut is not defined'); },     onLongPress: ()=>{ console.log('onLongPress is not defined'); },     onPress: ()=>{ console.log('onPress is not defined'); },     style: {},     image: null }; const styles = {     mainBtn:{         width:55,         height:55,         backgroundColor:'rgb(255,255,255)',       } };

首先,初始化PanResponder对象实例。它有一套不同的操作句柄。我感兴趣的是onPanResponderGrand(当用户触摸按钮时触发)和onPanResponderRelease(当用户从屏幕上移开手指时触发)两个句柄;

我还设置了一个动画对象实例,帮助我们处理动画。将其值设置为零;然后我们定义_setOpacity方法,调用时改变this.opacityAnimated的值。在渲染之前,我们插入this.opacityAnimated为正常的opacity值。我们不使用View而是使用Animated.View模块为了使用动态变化的opacity值。

通过上面的例子,你会发现Animated API不难理解,你只需要阅读相关的API文档,以确保你的应用程序***运行。希望这个例子能帮你开个好头。

以上是"使用React Native/Redux开发中会遇到什么错误"这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注行业资讯频道!

组件 布局 结构 样式 项目 错误 数据 模块 程序 页面 应用 开发 应用程序 存储 规划 不同 文件 代码 动画 属性 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 关于新基建和互联网科技 广州互联网科技公司 金融科技 互联网金融 奇酷互联网科技 西安互联网科技公司 掌上梦互联网科技 人人互联网科技是培训 盛创互联网科技有限公司 滨湖区互联网智能科技产品供应 哈尔滨新华互联网科技学院 顶级互联网科技成果有哪些 互联网科技项目计划书材料类 互联网科技公司实习生 互联网科技创新的路径 恒生互联网科技业指数调整周期 工业互联网展湾科技股份有限公司 2021互联网科技公司排名 智帮互联网科技公司最近动向 南京一网一红互联网科技有限公司 同城互联网络科技 云之行互联网科技 科技金融是不是互联网金融 华宇互联网科技 互联网 科技服务平台 深圳市优智互联网科技有限公司 天津腾达互联网科技有限公司 工业互联网展湾科技股份有限公司 互联网科技实习生岗位 上海乐五互联网科技有限公司 广东鹅鹅鹅互联网科技有限公司
0