1. 程式人生 > >React Native常見問題解答(一)

React Native常見問題解答(一)

呼叫setState之後發生了什麼?

在程式碼中呼叫setState函式之後,
1. React會將傳入的引數物件與元件當前的狀態合併,然後觸發所謂
的調和過程(Reconciliation)。
2. 經過調和過程,React會以相對高效的方式根據新的狀態構建React。
3. 元素樹並且著手重新渲染整個UI介面。
4. 在React得到元素樹之後,React會自動計算出新的樹與老樹的節點差異,
5. 根據差異對介面進行最小化重渲染。在差異計算演算法中,React能夠相對精確地知道哪些位置發生了改變
以及該如何改變,這就保證了按需更新,而不是全部重新渲染。

在生命週期中的哪一步你應該發起AJAX請求?為什麼?

將AJAX請求放到componentDidMount函式中執行。

原因如下:
1. React 下一代調和演算法Fiber會通過開始或停止渲染的方式優化效能,其會影響到componentWillMount
的觸發次數。對於componentWillMount這個生命週期函式的條用次數會變得不確定,React可能會多次頻繁呼叫componentWillMount。如果我們將AJAX請求放到componentWillMount函式中,那麼顯而易見
其會被觸發多次,自然也就不是好的選擇。
2. *如果我們將AJAX請求放置在生命週期的其他函式中,我們並不能保證請求僅在元件掛載完畢後
才會要求響應。如果我們的資料請求在元件掛載之前就完成,並且呼叫了setState函式將資料新增到
元件狀態中,對於未掛載的元件則會報錯。而在componentDidMount函式中進行AjAX請求則能有效避免
這個問題。

簡述React元件的生命週期

元件的生命週期可分成三個狀態:
1. Mounting:已插入真實DOM
2. Updating:正在被重新渲染
3. Unmounting:已移出真實DOM

生命週期的方法有:
- componentWillMount 在渲染錢呼叫,在客戶端也在伺服器
- componentDidMount 在第一次渲染後呼叫,只在客戶端。之後元件已經生成了對應的DOM結構,可以通過
this.getDOMNode()來進行訪問。如果你想和其他JavaScript框架一起使用,可以在這個方法中呼叫setTimeout,
setInterval或者傳送AJAX請求等操作(防止非同步操作阻塞UI)。
- componentWillReceiveProps 在元件接收到一個新的prop時被呼叫。這個方法在初始化render時不會被呼叫。
- shouldComponentUpdate 返回一個布林值。在元件接收到新的props或者state時被呼叫。在初始化時或者使用
forceUpdate時不被呼叫。可以在你確認不需要更新元件時使用。
- componentWillUpdate 在元件接收到新的props或者state但還沒有render時被呼叫。在初始化時不會被呼叫。
- componentDidUpdate 在元件完成更鬧心後立即呼叫。在初始化時不會被呼叫。
- componentWillUnmount 在元件從DOM中移除的時候立刻被呼叫。

React中keys的作用是什麼?特點?並舉例說明key的用法。

作用: keys是React用於追蹤哪些列表中元素被修改,被新增或者被移除的輔助標識。

    render() {
        return(
            <ul>
                { this.state.list.map(({item, key}) => {
                    return <li key={key}>{item}</li>
                })}
            </ul>
        );
    }

在開發過程中,我們需要保證某個元素的key在 其同級元素中具有唯一性。在React Diff演算法
中React會藉助元素額key值來判斷該元素是新近建立的還是被移動而來的元素,從而減少不必要
的元素重渲染。此外,React還需要藉助Key值來判斷元素與本地狀態的關聯關係,因此我們絕不可忽視轉換
函式中Key的重要性。

react native網路圖片載入不出來的原因是什麼?怎麼解決?

在IOS9版本以後,預設的網路請求是https,如果是http請求,需要手動解決。

  1. 找到info.plist檔案,用Xcode開啟。
  2. 找到App Transport Security Settings選項下的子選項Allow Arbitrary Loads
  3. 將Allow Arbitrary Loads 設定為YES

這裡寫圖片描述

假設資料來源為rows=[“row1”,”row2”,”row3”],請用listView展示rows的每一項

    import React, { Component} from 'react';
    import {
        ListView,
        View,
        Text
    } from 'react';


    export default class MyListView from Component {
        constructor(props) {
            super(props)
            var ds = ListView.DataSource({
                rowHasChanged: (r1, r2) => r1 !== r2
            });
            this.state = {
                dataSource: ds.cloneWidthRows(rows)
            }
        }
        _renderRow(item) {
            return (
                <View>
                    <Text>{item}</Text>
                </View>
            );
        }
        render() {
            return (
                <View style={{ flex: 1 }}>
                    <ListView
                        renderRow={ this._renderRow.bind(this) }
                        dataSource={ this.state.dataSource }
                    />
                </View>
            );
        }
    }

假設我有一個元件叫做FirstPage,請用Navigator實現以FirstPage為首頁的效果

    import React, { Component} from 'react';
    import {
        Navigator
    } from 'react-native';

    export default class Nav extends Component {
        render() {
            initialRoute = {
                component: FirstPage,
                nextPass: {}
            }
            return (
                <Navigator
                    initialRoute={ initialRoute }
                    configureScene={ (route) => Navigator.SceneConfigs.PushFromRight }
                    renderScene={ (route, navigator) => {
                        // 要渲染的頁面
                        var component = route.component;
                        // 渲染元件時,將元件的屬性也傳遞過去
                        return <Navigator { ...route.nextPass } route={ route } navigator={ navigator } />; 
                />
            );
        }
    }

請用TabBarIOS實現一個標籤欄,其中標籤欄包括兩個標籤,分別為首頁電影。其中首頁預設被選中

    import React, { Component } from 'react';
    import { 
        TabBarIOS,
        View,
        Text
    } from 'react-native';

    class HomeComponent extends Component {
        render() {
            return (
                <View>
                    <Text>這是首頁頁面</Text>
                </View>
            );   
        }
    }

    class MovieComponent extends Component {
        render() {
            return (
                <View>
                    <Text>這是電影頁面</Text>
                </View>
            );
        }
    }

    export default class TitleComponent extends Component {
        render() {
            return (
                <TabBarIOS>
                    <TabBarIOS.Item
                        title="首頁"
                        selected={ true }
                    >
                        <HomeComponent/>
                    </TabBarIOS.Item>
                    <TabBarIOS.Item
                        title="電影"
                    >
                        <MovieComponent/>
                    </TabBarIOS.Item>
                </TabBarIOS>
            );
        }
    }

shouldComponentUpdate的作用是啥以及為何它這麼重要?

shouldComponetUpdate允許我們手動地判斷是否要進行元件更新,根據元件的應用場景設定函式的合理返回值
能夠幫助我們避免不必要的更新。

為什麼我們需要使用React提供的Children API 而不是Javascript的map?

props.children並不一定是陣列型別,臂如下面這個元素:

<Parent>
    <h1>Welcom</h1>
</Parent>

如果我們使用props.children.map函式來遍歷時會受到異常提示,因為在這種情況下props.children
是物件(object)而不是陣列(array)。React當且僅當超過一個子元素的情況下會將props.children設定為陣列,就像
下面這個程式碼片:

<Parent>
    <h1>Welcom</h1>
    <h2>Hello World</h2>
</Parent>

這也就是我們優先選擇使用React.Children.map函式的原因,其已經將props.children不同型別的情況
考慮在內了。