2017-05-31 84 views
2

我遇到了新的FlatList組件的問題。具體來說,它不會重新渲染它的行,儘管該行依賴於更改的道具。React-native FlatList道具改變時不重排行


的FlatList文檔說:

這是一個PureComponent這意味着它不會重新渲染,如果 道具仍然淺海相等。確保renderItem 函數依賴的所有東西都作爲不是===的更新後的道具傳遞,否則您的UI可能無法更新更改。這包括數據 prop和父組件狀態。

問題

不過,看到我改變selectedCategory項目的ID - 我相信,道具應該重新解析 - 這應該表明該行是否是「選擇」與否的道具。我錯了嗎?

我檢查了列表和行組件的'componentWillReceiveProps'方法,列表接收到更新就好了,但行的生命週期方法從不調用。

如果我在列表組件中包含一個隨機的,無用的布爾值狀態值,並且在道具更新時來回切換,它會起作用 - 但我不知道爲什麼?

state = { updated: false }; 

componentWillReceiveProps(nextProps) { 
    this.setState(oldstate => ({ 
    updated: !oldstate.updated, 
    })); 
} 

<FlatList 
    data={this.props.items.allAnimalCategories.edges} 
    renderItem={this._renderRow} 
    horizontal={true} 
    keyExtractor={(item, index) => item.node.id} 
    randomUpdateProp={this.state.updated} 
/> 

THE CODE

我的代碼的結構是這樣的:我有與所有的邏輯和狀態的容器組件,其中包含一個FlatList組分(表象,無狀態),其中又包含一個自定義表示行。

Container 
    Custom list component that includes the FlatList component 
    (presentational, stateless) and the renderRow method 
    Custom row (presentational, stateless) 

該容器包括該組件:

<CustomList 
    items={this.props.viewer} 
    onCategoryChosen={this._onCategoryChosen} 
    selectedCategory={this.state.report.selectedCategory} 
/> 

CustomList:

class CustomList extends Component { 
    _renderRow = ({ item }) => { 
    return (
     <CustomListRow 
     item={item.node} 
     selectedCategory={this.props.selectedCategory} 
     onPressItem={this.props.onCategoryChosen} 
     /> 
    ); 
    }; 

    render() { 
    return (
     <View style={_styles.container}> 
     <FlatList 
      data={this.props.items.categories.edges} 
      renderItem={this._renderRow} 
      horizontal={true} 
      keyExtractor={(item, index) => item.node.id} 
      randomUpdateProp={this.state.updated} 
     /> 
     </View> 
    ); 
    } 

}

(數據來自繼電器)

最後行:

render() { 
    const idsMatch = this.props.selectedCategory.id == this.props.item.id; 
    return (
     <TouchableHighlight onPress={this._onItemPressed}> 
     <View style={_styles.root}> 
      <View style={[ 
       _styles.container, 
       { backgroundColor: this._getBackgroundColor() }, 
      ]}> 
      {idsMatch && 
       <Image 
       style={_styles.icon} 
       source={require('./../../res/img/asd.png')} 
       />} 
      {!idsMatch && 
       <Image 
       style={_styles.icon} 
       source={require('./../../res/img/dsa.png')} 
       />} 
      <Text style={_styles.text}> 
       {capitalizeFirstLetter(this.props.item.name)} 
      </Text> 
      </View> 
      <View style={_styles.bottomView}> 
      <View style={_styles.greyLine} /> 
      </View> 
     </View> 
     </TouchableHighlight> 
    ); 
    } 

該行並不那麼有趣,但我將它包括在內以表明它完全無狀態並依賴於它的父母道具。

的狀態更新,像這樣:

_onCategoryChosen = category => { 
    var oldReportCopy = this.state.report; 
    oldReportCopy.selectedCategory = category; 
    this.setState(Object.assign({}, this.state, { report: oldReportCopy })); 
    }; 

的狀態如下:

state = { 
    ... 
    report: defaultStateReport, 
    }; 

const defaultStateReport = { 
    selectedCategory: { 
    id: 'some-long-od', 
    name: '', 
    }, 
    ... 
}; 

回答

15

這裏的問題在於該

  1. 你是變異的事實中現有的狀態片,而不是創建變異副本

_onCategoryChosen = category => { 
    var oldReportCopy = this.state.report; // This does not create a copy! 
    oldReportCopy.selectedCategory = category; 
    this.setState(Object.assign({}, this.state, { report: oldReportCopy })); 
}; 

這應該是

_onCategoryChosen = category => { 
    var oldReportCopy = Object.assign({}, this.state.report); 
    oldReportCopy.selectedCategory = category; 
    // setState handles partial updates just fine, no need to create a copy 
    this.setState({ report: oldReportCopy }); 
}; 

  • FlatList的道具保持不變,您的_renderRow功能可以依賴於selectedCategory確實會改變的prop(如果不是第一個錯誤),但FlatList組件不知道這個。要解決此問題,請使用extraData支柱。

    <FlatList 
        data={this.props.items.categories.edges} 
        renderItem={this._renderRow} 
        horizontal={true} 
        keyExtractor={(item, index) => item.node.id} 
        extraData={this.props.selectedCategory} 
    /> 
    
  • +2

    非常感謝,這完美地工作。回想起來,extraData prop是使用FlatLists時非常重要且可能經常使用的工具 – jhm