2016-10-04 266 views
1

智能/啞組件使用選擇說我有一個最頂層的智能組件調用預測,看起來像這樣:在終極版

function mapStateToProps(state) { 
    return { 
    dates: state.getIn(['forecast', 'dates']), 
    isFetching: state.getIn(['forecast', 'isFetching']) 
    }; 
} 

export default connect(mapStateToProps, { 
    fetchForecast 
})(Forecast)); 

它包裝一個預測成分是這樣的:

import { getSummary, getDayForecast } from '../selectors/selectors'; 
export default class Forecast extends Component { 

    render() { 
    const { dates, isFetching } = this.props; 

    return (
     <div className="row"> 
     {dates.map(date => (
      <Weather 
      key={date} 
      date={date} 
      getSummary={getSummary} 
      getDayForecast={getDayForecast} 
      /> 
     ))} 
     </div> 
    ); 
    } 
}; 

這裏我將2個選擇器作爲道具傳遞給Weather組件。該選擇是這樣的:

import { createSelector } from 'reselect'; 
import moment from 'moment'; 
import { fromJS } from 'immutable'; 

const getDay = (state, key) => state.getIn(['forecast', 'forecast']).find(x => x.get('id') === key); 

export const getSummary = createSelector(
    [getDay], 
    (day => { 
    const firstPeriod = day.get('periods').first(); 

    return fromJS({ 
     date: day.get('date'), 
     outlook: firstPeriod.get('outlook'), 
     icon: firstPeriod.get('icon') 
    }); 
    }) 
); 

export const getDayForecast = createSelector(
    [getDay], 
    (day) => day.get('periods').map(period => fromJS({id: period.get('id') })) 
); 

我沒有通過這些選擇下來的道具,我可以很容易地只是參考他們在天氣組件,但我很困惑,我怎麼會用在這些選擇Weather組件作爲Weather組件也是愚蠢的,並且不會有任何狀態的引用。我只想要一個容器或智能組件在頂層,子組件調用或獲取道具傳遞。

我可以看到使這項工作的唯一方法是有一個intermediatary WeatherContainer組件,它看起來是這樣的:

import React, { Component, PropTypes } from 'react'; 
import { connect } from 'react-redux'; 

import Weather from '../components/Weather'; 

import { getSummary, getDayForecast } from '../selectors/selectors'; 

function mapStateToProps(state, ownProps) { 
    return { 
    summary: getSummary(state, ownProps.date), 
    detail: getDayForecast(state, ownProps.date) 
    }; 
} 

export default(connect(mapStateToProps,{}))(Weather); 

,我會叫這樣的:

{dates.map(date => (
     <WeatherContainer 
     key={date} 
     date={date} 
     getSummary={getSummary} 
     getDayForecast={getDayForecast} 
     /> 
    ))} 

這似乎必須創建像這樣的容器組件是完全錯誤的。

我怎樣才能使啞元件使用選擇的或如何傳遞下來的道具記住霸菱,他們也需要參照狀態?

+0

你的選擇器返回的是不可變的對象,這是過度殺傷。與普通物體相比,它的性能也更差,也更難使用。把React-Redux上下文中的'props'想象成一個臨時變量。這是不變的,但沒有必要執行或管理。 – DDS

回答

4

在你WeatherContainermapStateToProps你用你的選擇,但你仍然傳遞下來的道具。這不是必需的。

除此之外,你應該知道,在創建容器WeatherContainer是去了解事情的正確方法。你應該從來沒有給組件一個選擇器。它們應該始終在mapStateToProps中使用。 React-Redux將在狀態更改時重新評估此值,並在結果不同時告訴React更新組件。這是非常重要的一點。如果你只是搶到一個組件內的狀態,是否使用選擇與否,隨即反應過來,終極版不知道你正在使用此數據不會,我們能夠告訴反應,重新描繪當此數據變化。

現在很多人都對這件事感到困惑。有愚蠢的組件,只是顯示的東西,和容器組件,其中東西,就像進行API調用或實現排序功能。但是當你把一個愚蠢的組件和connect它給Redux,那麼這不會成爲一個智能或容器組件。它仍然只顯示東西。即使您使用mapDispatchToProps來爲某些事件偵聽器提供它,但這仍然不能使組件變得更加智能。如果它包含mapStateToPropsmapDispatchToProps中的重要代碼,我想可能會變得很聰明。但這就是生活。這些事情之間的界限只是模糊。

Redux Way是連接需要數據的所有東西。您一定可以將數據傳遞給孩子,就像使用普通的React一樣,但您可以通過連接組件來創建更高性能的應用程序。不過,這取決於你自己決定。但是任何你從商店獲取數據的地方都很重要,它應該放在mapStateToProps之內,這樣React-Redux可以關注數據。只要數據來自mapStateToProps,您就可以安全地將其從父母傳遞給孩子。

這意味着將選擇器傳遞給孩子是一個禁忌。另外,孩子在哪裏將狀態作爲參數傳遞給選擇器?它工作不好,所以這不是一個好主意。請注意,無論何時您使用connect組件,您都不會創建一個全新的組件。只是一個簡單的包裝。它應該在很少的幾行中包含非常少的代碼。這不應該讓你停下來。只是爲了它。 connect這些組件。

我還應該提到,您可以直接在weather.js文件中連接Weather組件。除非您要重複使用它,否則不需要保留未連接的組件。對於測試,您可以使用命名導出export未連接的組件。如果稍後決定需要重新使用Weather組件,則始終可以輕鬆地將組件和連接呼叫分離爲單獨的文件。

+0

如果我點擊一個父組件進行異步調用以獲取並顯示該父項的子記錄,那麼如果我有一個主/子場景會怎麼樣。選擇器對此有用嗎? 我只想在第一時間撥打電話,而不是在此後撥打 – dagda1

+0

號碼。這是一個禁忌,因爲您需要發送操作將該數據放入Redux存儲,並讓Redux執行任何必要的重新顯示操作* for *你,孩子的組成部分或兄弟姐妹或任何地方。這是好處的一部分:現在或未來版本的應用程序中依賴於此數據的任何內容都會得到更新,並有保證。這是Redux的*主要優勢*:應用程序的每個部分都同意這些數據。這實際上並不取決於您想要對API或後端或朋友進行多少次調用,也不取決於何時以及如何調用。 – DDS

+0

選擇器將用於從商店獲取數據。使用選擇器的原因是,當商店形狀改變時,選擇器和選擇器可以被修改以返回正確的數據。選擇器也可以調用其他(父)選擇器,所以如果你移動狀態片,你可能只需要改變一個選擇器。有時選擇器也可以格式化數據,但它們確實是格式化器。不過,[Reselect](https://github.com/reactjs/reselect)或其他通用[memoizers](https://gist.github.com/addyosmani/1225243),對於格式化程序也可以正常工作。 – DDS