2016-08-02 86 views
6

在使用Redux在大React Native應用程序中導航期間,所有訪問的場景(導航堆棧的場景)都將保持安裝狀態。所有這些場景都會接收道具,並在從最後一個場景組件分派任何動作時按照它們訪問的順序進行渲染。它會導致凍結和分派與上次場景呈現之間的可見延遲。React Native/Redux應用程序中的可能導航問題

對於導航,我正在使用react-native-router-flux,但原來的React Native Navigator也出現了同樣的問題。

視頻Possible navigation issues in React Native/Redux app

代碼react-redux-navigation-test

會很高興地知道如何防止通過道具不是從導航鏈集中的組件。

此刻,我正在檢查每個組件的shouldComponentUpdate,如果這個組件是聚焦(可見)並在相反的情況下返回false。

有沒有更好的解決方案?

+0

HI!我與我的護士應用程序有同樣的問題。你有沒有找到解決方法? – David

回答

0

我還沒有使用react-native-router-flux,但是我有一個相當大的React Native和Redux應用程序的經驗。我注意到,有時如果你所使用的數據變得足夠大,可能會引起明顯的延遲,但這些數據大多侷限於在開發中工作。當應用程序建立時,它通常明顯更快。看起來好像Redux在開發和生產模式中有些不同。

關於仍在安裝導航堆棧中的場景,這是有意設計的。即使您將navigator.push更改爲另一個屏幕,那些以前的屏幕仍會保持安裝狀態,直到它們從currentRouteStack彈出或由currentRouteStack替換。

另外,可能值得注意的是您的模擬器處於慢動畫模式。不知道你是否爲了視頻而做了這件事,但導航遲緩的部分原因在於此。只是在沒有故意的情況下提出來。

我會檢查應用程序在創建完成後如何工作,並且在進一步排除性能問題之前,它不處於開發模式。可能不是最終應用產品的問題。

+0

謝謝你這麼快的回答。此問題也發生在生產模式下的真實設備上。這些延遲主要取決於導航堆棧的大型場景。在上面的示例中,在開始場景中顯示了1000個元素的巨大列表,以強調這些延遲。在真正的應用程序中,我正在努力處理這些延遲並不那麼大但很重要。 視頻示例中場景之間的轉換等於2s。不是慢模式。 所以我正在尋找更好的方法來防止渲染,甚至道具傳遞不可見的場景。目前我正在使用檢查shouldComponentUpdate – alexsh

+0

嗯,有趣。我看到你正在將這些元素渲染成ScrollView。我會很好奇看看ListView會對性能產生什麼影響。我相信他們用來渲染ListView行還有額外的性能改進。可能值得研究。 – jasonmerino

2

我建議您使用場景和標題渲染方法中的導航索引來計算當前場景和場景之間的場景距離。如果距離> 1返回null。

這應該防止呈現整個導航歷史記錄。對我來說,這種行爲不是開箱即用的,但它確實存在。

0

我打算在這裏出現肢體,但是您是否使用以下方法之一來防止重新渲染?

  • PureComponents(在加入陣營15.3我覺得)手動淺
  • 比較shouldComponentUpdate方法道具和狀態。

默認情況下,React將在更新時重新呈現所有組件,除非您正確處理shouldComponentUpdate。

我在做類似的事情,並在所有

0

的問題確實是整個導航堆棧連接到店裏沒有這些問題(因爲除非你使用resetto或resetnavigation部件不卸載)

這裏值得一提的是我現在要做的。 我一直在使用稍加修改的反應終極版的實現,跳過對於不考慮場景更新(見下文)

要使用它,你需要:

存儲在上下文中一個組件樹的路徑

我們創建了一個包裝爲此

const CurrentRoute = React.createClass({ 
childContextTypes : { currentRoute: PropTypes.object }, 
getChildContext() { 
return { currentRoute: this.props.route } 
}, 
render() { return this.props.children; } 
}) 

並用它在渲染場景

<CurrentRoute route={route}><CurrentScene navigate={navigate} route={route} index={index} /></CurrentRoute> 

然後,您可以訪問組件已被渲染到的路線。

存放在單 導航堆棧,我們在配置場景中使用此代碼

let routeStack = []; 
export const updateRouteStack = stack => routeStack = stack; 

然後你可以使用這個稍微修改反應,Redux的連接功能,它會跳過更新,如果組件在另一個組件呈現樹那麼當前顯示的一個 (或類似實現) https://github.com/reactjs/react-redux/compare/master...ganmor:master

可能可以打包這一點,但我還沒有時間去考慮它。如果有人覺得這樣做.. 希望可以幫助

0

我們通過簡單地將所有屏幕包裝在組件中來解決它。

我們有一個ScreenView組件包裝了整個屏幕,並且我們傳遞了一個參數「restrictRerendersToRoutes」。

此屏幕連接到狀態,我們更新我們狀態下的currentScrene並將其暴露給此屏幕視圖。

然後我們簡單地限制重新渲染當屏幕背景與此shouldComponentUpdate實現:

shouldComponentUpdate(nextProps) { 
    if (!_.empty(this.props.restrictRerendersToRoutes)) { 
     return !!this.props.restrictRerendersToRoutes 
     .find((routeKey) => routeKey === nextProps.currentScene.name); 
    } 

    return true; 
    } 
+0

你能否提供一個更詳細的例子,這將是非常有用的。謝謝! – David

相關問題