中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

使用React Native/Redux開發中會遇到什么錯誤

發布時間:2021-09-06 16:07:01 來源:億速云 閱讀:136 作者:小新 欄目:web開發

這篇文章主要為大家展示了“使用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”頁面?

我遇到并開始實施的***個結構是這樣的:

使用React Native/Redux開發中會遇到什么錯誤

如果你的項目不超過10個頁面,使用上面這種結構是沒有問題的。但是如果項目特別大 – 你可以考慮這樣規劃結構:

使用React Native/Redux開發中會遇到什么錯誤

區別在于,***種類型建議我們將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 &lsquo;react&rsquo;; import {    Text,    TextInput,    View,    TouchableOpacity } from &lsquo;react-native&rsquo;; import styles from &lsquo;./styles.ios&rsquo;;  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(&lsquo;Please, enter username&rsquo;);        }     }                     render() {               return (                     <View style={styles.container}>                         <View style={styles.avatarBlock}>                                 <Image                         source={this.props.image}                          style={styles.avatar}/>                         </View>                         <View style={styles.form}>                 <View style={styles.formItem}>                    <Text>Username</Text>                     <TextInput                          onChange={this._usernameChanged.bind(this)}                          value={this.state.username} />                  </View>             </View>             <TouchableOpacity onPress={this._submit.bind(this)}>                                 <View style={styles.btn}>                                         <Text style={styles.btnText}>                             Submit                                             </Text>                 </View>              </TouchableOpacity>         </View>         );     } }

所有樣式都存儲在一個單獨的模塊中。

包裹在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(                                 <View style={styles.avatarBlock}>                     <Image                         source={this.props.imgSrc}                         style={styles.avatar}/>                 </View>              )          }          return null;     } } Avatar.propTypes = {     imgSrc: PropTypes.object }  class FormItem extends Component{     constructor(props){         super(props);     }     render(){         let title = this.props.title;         return(              <View style={styles.formItem}>                 <Text>                     {title}                                </Text>                <TextInput                    onChange={this.props.onChange}                    value={this.props.value} />             </View>         )     } } 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(                         <TouchableOpacity onPress={this.props.onPress}>                 <View style={styles.btn}>                     <Text style={styles.btnText}>                         {title}                                         </Text>                 </View>             </TouchableOpacity>         )     } }              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 (                                          <View style={styles.container}>                 <Avatar imgSrc={this.props.image} />                 <View style={styles.form}>                     <FormItem                       title={"Username"}                       value={this.state.username}                       onChange={this._usernameChanged.bind(this)}/>                 </View>                 <Button                     title={"Submit"}                     onPress={this._submit.bind(this)}/>             </View>         );     } }

現在的代碼看起來更多了 &ndash;  因為我們為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(                         <TouchableOpacity onPress={this.props.onPress}>                 <View style={styles.btn}>                     <Text style={styles.btnText}>                         {title}                                         </Text>                </View>            </TouchableOpacity>         )     } } 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 (                         <View style={styles.container}>                 <Button                     id={0}                     onPress={this._submit.bind(this)}/>             </View>              } }

我們已經“升級”了Button組件。用一個叫做“id”的新屬性來替換屬性“title”。現在Button組件就變的“靈活”了。傳0 &ndash;  button組件會顯示“submit”。傳2 &ndash; 顯示“delete”。但這可能會有一些問題。

Button被創建為一個dumb組件 &ndash; 只是為了顯示數據,傳遞數據這件事由它的更高一級的組件來完成。

如果我們將5作為id傳遞給這個組件,我們就需要更新組件,以便讓它適應這個改動。dumb組件,就是細分的小組件,它只要接收props就好了,如果有state也應該與全局的無關。

7.行內樣式

在使用RN布局之后,我遇到了行內樣式的寫作風格問題。類似這樣:

render() {         return (                 <View style={{flex:1, flexDirection:'row', backgroundColor:'transparent'}}>             <Button                 title={"Submit"}                 onPress={this._submit.bind(this)}/>         </View>     ); }

當你這樣寫的時候,你會想:“暫時這樣寫,等我在模擬器中運行之后 &ndash;  如果布局沒問題,再把樣式移動到單獨的模塊。”也許這是一個好的想法。但是..不幸的是,你往往會選擇性忽略行內樣式&hellip;

一定要在獨立的模塊中編寫樣式,遠離行內樣式。

8.使用redux驗證表單

要使用redux來驗證表單,我需要在reducer中創建action,actionType單獨的字段,這樣做很麻煩。

所以我決定只借助state來完成驗證。沒有reducers,types等等,只是在container級別上的純功能函數。從action和reducer文件中刪除不必要的函數,這個策略對我幫助很大。

9.過于依賴zIndex

很多人從web開發轉到RN開發。在web中有一個css屬性z-index,它可以幫助我們在需要的層級顯示我們想要的內容。

在RN中,一開始沒有這樣的特性。但后來又被添加進來了。起初,使用起來還挺簡單的。只需為元素設置zIndex屬性,它就會按照任何你想要的圖層順序來渲染。但是在Android上測試之后&hellip;現在我只用zIndex來設置展示層的結構。

10.不仔細閱讀外部組件的源碼

你可以引入外部組件來節省你的開發時間。

但有時這個模塊可能會中斷,或者不像描述的那樣工作。閱讀源碼你才會明白哪里出現了錯誤。也許這個模塊本身就有問題,或者你只是用錯了。另外 &ndash;  如果你仔細閱讀其他模塊的源碼,你將會學習到如何構建自己的組件。

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

RN為我們提供了構建完全原生應用程序的能力。怎么讓用戶感覺是原生應用?頁面布局,滑動手勢,還是展示動畫?

當你使用View,Text,TextInput和其他RN提供的默認模塊時,手勢和動畫應該由PanResponder和Animated  API來處理。

如果你是從web轉過來的rn開發工程師,獲取用戶的手勢操作可能會有些困難,你需要區分什么時候開始,什么時候結束,長按,短按。你可能還不夠清楚怎么在RN中模擬這些動畫操作。

這是我用PanResponder和Animated建立的Button組件。這個button是為了捕捉用戶手勢而構建的。例如 &ndash;  用戶按下項目,然后將手指拖到一邊。在按下按鈕時,借助于動畫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(                         <View style={styles.btn}>                 <Animated.View                    {...this.panResponder.panHandlers}                   style={[styles.mainBtn, this.props.style, {opacity:opacity}]}>                     {image}                                </Animated.View>             </View>         )     } } 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開發中會遇到什么錯誤”這篇文章的所有內容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內容對大家有所幫助,如果還想學習更多知識,歡迎關注億速云行業資訊頻道!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

天镇县| 邢台市| 正镶白旗| 庆云县| 博野县| 定结县| 英德市| 普陀区| 乌鲁木齐市| 大荔县| 江西省| 广南县| 西城区| 太和县| 九龙坡区| 怀来县| 平定县| 大宁县| 霞浦县| 微山县| 普格县| 曲水县| 大英县| 琼海市| 宁津县| 宜城市| 长丰县| 江城| 思南县| 肇源县| 中宁县| 乐至县| 潜山县| 玛沁县| 赣州市| 澎湖县| 文登市| 万盛区| 新营市| 井陉县| 杨浦区|