จะ re-render flatlist ได้อย่างไร?


88

ซึ่งแตกต่างจาก ListView ที่เราสามารถอัปเดต this.state.datasource มีวิธีการหรือตัวอย่างในการอัปเดต FlatList หรือ re-render หรือไม่?

เป้าหมายของฉันคืออัปเดตค่าข้อความเมื่อผู้ใช้กดปุ่ม ...

renderEntries({ item, index }) {
    return(
        <TouchableHighlight onPress={()=> this.setState({value: this.state.data[index].value+1})>
             <Text>{this.state.data[index].value}</Text>
        </TouchableHighlight>
    )
}

<FlatList 
    ref={(ref) => { this.list = ref; }} 
    keyExtractor={(item) => item.entry.entryId} 
    data={this.state.data} 
    renderItem={this.renderEntries.bind(this)} 
    horizontal={false} />

8
เอกสารสำหรับ FlatListพูดว่า "นี่คือPureComponentซึ่งหมายความว่ามันจะไม่ทำให้อีกครั้งหากยังคงประกอบฉาก shallow- เท่ากับ. ตรวจสอบให้แน่ใจว่าทุกอย่างของคุณrenderItemฟังก์ชั่นขึ้นอยู่กับจะถูกส่งเป็นเสาที่ไม่ได้เป็น===หลังจากการปรับปรุงอย่างอื่น UI ของคุณอาจไม่ปรับปรุง เกี่ยวกับการเปลี่ยนแปลงซึ่งรวมถึงdataสถานะส่วนประกอบหลักและส่วนประกอบหลัก " คุณทำตามคำแนะนำนี้หรือไม่?
Jordan Running

3
ไม่ว่าฉันจะพยายามด้วยวิธีใดextraDataและshouldItemUpdateฉันไม่สามารถรับรายการเพื่อเรนเดอร์ใหม่ได้ สิ่งที่ฉันทำคือการล้างสถานะรอให้แสดงผลแล้วอัปเดตสถานะ this.setState({ data: null }, () => { this.setState({ data: actualData }) });
Joshua Pinter

คำตอบ:


193

ใช้extraDataคุณสมบัติบนคอมโพเนนต์ FlatList ของคุณ

ตามเอกสารระบุ:

เมื่อส่งextraData={this.state}ถึงFlatListเราต้องแน่ใจว่าFlatListจะแสดงผลอีกครั้งเมื่อมีstate.selectedการเปลี่ยนแปลง หากไม่มีการตั้งค่าเสานี้FlatListจะไม่ทราบว่าจำเป็นต้องแสดงรายการใด ๆ อีกครั้งเนื่องจากเป็น a PureComponentและการเปรียบเทียบเสาจะไม่แสดงการเปลี่ยนแปลงใด ๆ


36
ฉันใช้ Redux และในกรณีที่การส่งข้อมูลเช่นdata={this.props.searchBookResults}และค่าextraData={this.state}มิได้extraData={this.props}คือการทำงานสำหรับฉัน และdata={this.props.searchBookResults}ไม่ทำงานด้วย. จะทำอย่างไร?
Sujit

11
ใช้ extraData: เพื่อรีเฟรช <FlatList> ของคุณ... data={this.props.searchBookResults} extraData={this.state.refresh} onPress={()={this.setState({ refresh: !refresh})}
เปล่า

9
ฉันกำลังต่อสู้กับปัญหาเดียวกัน ไม่สำคัญว่าฉันจะส่งต่ออะไรextraDataส่วนประกอบไม่อัปเดต :(
Denis Cappelini

2
@DenisCappelini ตรวจสอบให้แน่ใจว่าข้อมูลที่ส่งผ่านไปยังextraDataเสามีการเปลี่ยนแปลงเมื่อรายการลูกต้องแสดงผลอีกครั้ง ตัวอย่างเช่นถ้ารายการสามารถใช้งาน / ไม่ได้ใช้งานให้ตรวจสอบว่าตัวแปรสถานะไม่ว่าจะเป็นส่วนหนึ่งของthis.stateวัตถุหรือวัตถุเป็นสิ่งที่ควรจะไปภายในthis.props extraDataอาจเป็นเคอร์เซอร์หรืออาร์เรย์ของรายการที่ใช้งานอยู่เป็นต้น
Emperor_Earth

1
@Sujit ฉันพบปัญหาเดียวกัน แต่แล้วฉันก็รู้ว่าฉันได้ใช้งานshouldComponentUpdate()แล้วเมื่อฉันอัปเดตหรือแสดงความคิดเห็นอย่างสมบูรณ์สิ่งต่างๆทำงานได้ตามที่อธิบายไว้ในเอกสาร
JanithaR

54

สำหรับวิธีแก้ปัญหาที่ง่ายและรวดเร็วลอง:

  1. ตั้งค่าข้อมูลเพิ่มเติมเป็นค่าบูลีน

    extraData = {this.state.refresh}

  2. สลับค่าของสถานะบูลีนเมื่อคุณต้องการ re-render / refresh list

    this.setState({ 
        refresh: !this.state.refresh
    })
    

นั่นคือสิ่งที่ฉันต้องการเนื่องจากฉันจะเพิ่มข้อมูลลงใน data prop นอกจากนี้นั่นเป็นการใช้งานที่แปลกประหลาดโดยทีม React-Native ... มันสมเหตุสมผลกว่าที่จะมีฟังก์ชั่นรีเฟรชหรือคุณสมบัติบนข้อมูล this.data.refresh()IE: แต่เราตั้งค่าบูลีนและเปลี่ยนมัน ค่าบูลีนเองก็ไม่มีความหมายดังนั้นจุดที่มีอยู่ในนั้นคืออะไร ... (ไม่มีประเด็นอื่นนอกจากการรีเฟรชข้อมูลใช่ไหม)
YungGun

@HradeshKumar ฉันทำ แต่รายการสุดท้ายใน Data มันไม่สามารถหายไปได้!
DevAS

มันใช้งานได้เหมือนมีเสน่ห์ แต่ฉันก็ยังไม่รู้ว่าทำไมถึงใช้this.state.usersไม่ได้แม้ว่าฉันจะเปลี่ยนธงในผู้ใช้บางคน
shyammakwana.me

ไม่ได้ผลสำหรับฉันคุณช่วยได้ไหม: stackoverflow.com/questions/65547030/…
Gayatri Dipali

21

ง่ายมากแค่ใช้ extraData

คุณเห็นวิธีการทำงานของข้อมูลเพิ่มเติมเบื้องหลังคือFlatListหรือVirtualisedListเพียงแค่ตรวจสอบว่าวัตถุมีการเปลี่ยนแปลงผ่านทางปกติonComponentWillReceivePropsวิธีการ

ดังนั้นสิ่งที่คุณต้องทำคือตรวจสอบให้แน่ใจว่าคุณได้ให้สิ่งที่เปลี่ยนแปลงไปในไฟล์extraData.

นี่คือสิ่งที่ฉันทำ:

ฉันใช้js ที่ไม่เปลี่ยนรูปดังนั้นสิ่งที่ฉันทำคือส่งแผนที่ (วัตถุที่ไม่เปลี่ยนรูป) ที่มีสิ่งที่ฉันต้องการดู

<FlatList
    data={this.state.calendarMonths}
    extraData={Map({
        foo: this.props.foo,
        bar: this.props.bar
    })}
    renderItem={({ item })=>((
        <CustomComponentRow
            item={item}
            foo={this.props.foo}
            bar={this.props.bar}
        />
    ))}
/>

ด้วยวิธีนั้นเมื่อใดthis.props.fooหรือthis.props.barเปลี่ยนแปลงเราCustomComponentRowจะอัปเดตเนื่องจากวัตถุที่ไม่เปลี่ยนรูปจะเป็นวัตถุที่แตกต่างจากก่อนหน้านี้


2
ในที่สุดฉันก็เข้าใจextraData! ขอบคุณสำหรับลิงค์ไปยังVirtualisedListรหัส!
Tushar Koul

สวัสดี @ SudoPiz ฉันต้องการแสดง Flatlist อีกครั้งหลังจากลบรายการสุดท้ายสามารถตรวจสอบ Q stackoverflow.com/questions/58780167/…
Oliver D

6

ตกลงฉันเพิ่งค้นพบว่าถ้าเราต้องการให้ FlatList ทราบการเปลี่ยนแปลงข้อมูลภายนอก data prop เราต้องตั้งค่าเป็น extraData ดังนั้นฉันจึงทำเช่นนี้ทันที:

<FlatList data={...} extraData={this.state} .../>

อ้างถึง: https://facebook.github.io/react-native/docs/flatlist#extradata


2
การใช้งานที่ดีที่สุด ... ฉันต้องการตั้งค่าให้เหมือนกับ data prop ดังนั้นจึงไม่รีเฟรชเมื่อมีการเปลี่ยนแปลงสถานะใด ๆ แต่นี่เป็นการใช้งานที่ง่ายที่สุด ขอบคุณ!
Robert Kehoe

สวัสดี @MahdiBashirpour ฉันต้องการแสดง Flatlist อีกครั้งหลังจากลบรายการสุดท้ายสามารถตรวจสอบ Q stackoverflow.com/questions/58780167/…
Oliver D

4

หากคุณกำลังจะมีปุ่มคุณสามารถอัปเดตข้อมูลด้วย setState ภายใน onPress จากนั้น SetState จะแสดง FlatList ของคุณอีกครั้ง


3
มี setState อยู่ในไฮไลท์สัมผัสของฉัน setState ใช้งานได้ดี แต่แฟลตลิสต์ไม่แสดงการอัปเดตค่าสถานะ -> this.state.value
shalonteoh

ค่าใน FlastList ของคุณไม่อัปเดตเนื่องจากคุณไม่ได้อัปเดตแหล่งข้อมูลโดยตรง this.state.data คือสิ่งที่แสดงผลด้วย FlatList แต่ใน onPress คุณกำลังอัปเดต this.state.value เท่านั้น
WilliamC

ขอโทษที่ผิดพลาดคำถามพิมพ์ผิด ควรเป็น this.state.data [ดัชนี]
.value

4

หลังจากค้นหามากมายและมองหาคำตอบที่แท้จริงในที่สุดฉันก็ได้คำตอบที่คิดว่าดีที่สุด:

       <FlatList
      data={this.state.data}
      renderItem={this.renderItem}
      ListHeaderComponent={this.renderHeader}
      ListFooterComponent={this.renderFooter}
      ItemSeparatorComponent={this.renderSeparator}
      refreshing={this.state.refreshing}
      onRefresh={this.handleRefresh}
      onEndReached={this.handleLoadMore}
      onEndReachedThreshold={1}
      extraData={this.state.data}
      removeClippedSubviews={true}
      **keyExtractor={ (item, index) => index }**
              />
    .....

ปัญหาหลักของฉันคือ (KeyExtractor) ฉันไม่ได้ใช้มันแบบนี้ ไม่ทำงาน: keyExtractor = {(item) => item.ID} หลังจากที่ฉันเปลี่ยนเป็นสิ่งนี้มันใช้งานได้ดีฉันหวังว่านี่จะช่วยใครบางคนได้


คุณใส่ค่าthis.state.refreshingและฟังก์ชันได้handleRefreshไหม
DevAS

2

เพียงส่วนขยายของคำตอบก่อนหน้านี้ที่นี่ สองส่วนเพื่อให้แน่ใจว่าคุณได้เพิ่ม extraData และ keyExtractor ของคุณไม่ซ้ำกัน หาก keyExtractor ของคุณคงที่การแสดงผลจะไม่ถูกทริกเกอร์

<FlatList
data={this.state.AllArray}
extraData={this.state.refresh}
renderItem={({ item,index })=>this.renderPhoto(item,index)}
keyExtractor={item => item.id}
>
                                    </FlatList>

1

ฉันแก้ไขปัญหานี้โดยการเพิ่มextraData={this.state}Please check code ด้านล่างเพื่อดูรายละเอียดเพิ่มเติม

render() {
    return (
      <View style={styles.container}>
        <FlatList
          data={this.state.arr}
          extraData={this.state}
          renderItem={({ item }) => <Text style={styles.item}>{item}</Text>}
        />
      </View>
    );
  }

0

ฉันได้เปลี่ยนFlatListด้วยSectionListและจะมีการปรับปรุงอย่างถูกต้องในการเปลี่ยนสถานะ

<SectionList
  keyExtractor={(item) => item.entry.entryId} 
  sections={section}
  renderItem={this.renderEntries.bind(this)}
  renderSectionHeader={() => null}
/>

สิ่งเดียวที่ต้องจำไว้คือsectionมีโครงสร้างที่แตกต่างกัน:

const section = [{
  id: 0,
  data: this.state.data,
}]

0

สำหรับฉันเคล็ดลับคือ extraData และเจาะลึกลงไปในส่วนประกอบของรายการอีกครั้ง

state = {
  uniqueValue: 0
}

<FlatList
  keyExtractor={(item, index) => item + index}
  data={this.props.photos}
  renderItem={this.renderItem}
  ItemSeparatorComponent={this.renderSeparator}
/>

renderItem = (item) => {
  if(item.item.selected) {
    return ( <Button onPress={this.itemPressed.bind(this, item)}>Selected</Button> );
  }
  return ( <Button onPress={this.itemPressed.bind(this, item)}>Not selected</Button>);
}

itemPressed (item) {
  this.props.photos.map((img, i) => {
    if(i === item.index) {
      if(img['selected') {
        delete img.selected;
      } else {
        img['selected'] = true;
      }
      this.setState({ uniqueValue: this.state.uniqueValue +1 });
    }
  }
}

0

ใส่ตัวแปรที่จะเปลี่ยนแปลงโดยการโต้ตอบของคุณที่ extraData

คุณสามารถมีความคิดสร้างสรรค์

ตัวอย่างเช่นหากคุณกำลังจัดการกับรายการที่เปลี่ยนแปลงโดยมีช่องทำเครื่องหมายอยู่

<FlatList
      data={this.state.data.items}
      extraData={this.state.data.items.length * (this.state.data.done.length + 1) }
      renderItem={({item}) => <View>  

0

หากเราต้องการให้ FlatList ทราบว่าข้อมูลเปลี่ยนแปลงทั้ง prop และ stateเราสามารถสร้าง object ที่อ้างอิงทั้ง prop และ state และรีเฟรช flatlist

const hasPropOrStateChange = { propKeyToWatch: this.props, ...this.state};
<FlatList data={...} extraData={this.hasPropOrStateChange} .../>

เอกสาร: https://facebook.github.io/react-native/docs/flatlist#extradata


0

ใน react-native-flatlist เป็นคุณสมบัติที่เรียกว่า extraData เพิ่มบรรทัดด้านล่างในแฟลตลิสต์ของคุณ

 <FlatList
          data={data }
          style={FlatListstyles}
          extraData={this.state}
          renderItem={this._renderItem}
       />

0

ในตัวอย่างนี้หากต้องการบังคับให้ re-render เพียงแค่เปลี่ยนตัวแปร machine

const [selected, setSelected] = useState(machine)

useEffect(() => {
    setSelected(machine)
}, [machine])

-1

เพียงใช้:

onRefresh={true}

ภายในflatListส่วนประกอบของคุณ


1
นี้จะสร้างข้อผิดพลาดต้อง u แล้วใช้refreshingไม้ค้ำยัน
mahmoudafer

-1

extraData ของ Flatlist ไม่ได้ผลสำหรับฉันและฉันบังเอิญใช้ prop จาก redux สิ่งนี้ฟังดูเหมือนกับปัญหาจากความคิดเห็นในคำตอบของ ED209 ฉันลงเอยด้วยการโทรหา setState ด้วยตนเองเมื่อฉันได้รับ prop

componentWillReceiveProps(nextProps: StateProps) {
    if (this.props.yourProp != null && nextProps.yourProp) {
        this.setState({ yourState: processProp(nextProps.yourProp) });
    }
}


<FlatList
  data={this.state.yourState}
  extraData={this.state.yourState}
/>

สำหรับผู้ที่ใช้> React 17 ให้ใช้getDerivedStateFromProps

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.