如何重新渲染平面列表?

时间:2017-04-13 16:53:24

标签: reactjs react-native react-native-flatlist

与ListView不同,我们可以更新this.state.datasource。是否有任何方法或示例来更新FlatList或重新渲染它?

我的目标是在用户按下按钮时更新文本值...

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} />

18 个答案:

答案 0 :(得分:123)

使用FlatList组件上的extraData属性。

正如文件所述:

  

通过将extraData={this.state}传递给FlatList,我们确保FlatList本身会在state.selected更改时重新呈现。如果没有设置此道具,FlatLis t就不会知道需要重新渲染任何项目,因为它也是PureComponent并且道具比较不会显示任何更改。

答案 1 :(得分:23)

快速简单的解决方案尝试:

  1. 将额外数据设置为布尔值。

    =而额外{this.state.refresh}

  2. 当您想重新渲染/刷新列表

    时,切换布尔状态的值
    this.setState({ 
        refresh: !this.state.refresh
    })
    

答案 2 :(得分:14)

哦,这很简单,只需使用extraData

您会看到额外数据在幕后工作的方式是 FlatList VirtualisedList 只是通过普通onComponentWillReceiveProps方法检查wether that object has changed

所以你要做的就是确保你给extraData改变了一些东西。

这就是我的所作所为:

我正在使用immutable.js所以我所做的就是传递一个包含我想要观看的内容的Map(不可变对象)。

<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.foothis.props.bar发生变化时,我们的CustomComponentRow会更新,因为不可变对象将与之前的对象不同。

答案 3 :(得分:4)

如果您要使用Button,则可以使用onPress中的setState更新数据。然后,SetState将重新渲染FlatList。

答案 4 :(得分:4)

好的。我刚刚发现,如果我们希望FlatList知道数据属性之外的数据更改,我们需要将其设置为extraData,所以我现在就这样:

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

请参阅:DRF Source-Code

答案 5 :(得分:2)

我通过添加public class DataAccess { private static AsyncHttpClient client = new AsyncHttpClient(); public static void get(Context context, String url, RequestParams params, AsyncHttpResponseHandler responseHandler) { client.get(getAbsoluteUrl(url), params, responseHandler); } public static void post(String url, RequestParams params, AsyncHttpResponseHandler responseHandler) { client.post(getAbsoluteUrl(url), params, responseHandler); } private static void start() { } private static String getAbsoluteUrl(String relativeUrl) { return Settings.serverLink + relativeUrl; } } 解决了此问题,请查看下面的代码以获取更多详细信息

extraData={this.state}

答案 6 :(得分:1)

这里只是先前答案的扩展。 确保两部分,请确保添加extraData且keyExtractor是唯一的。如果您的keyExtractor是常量,则不会触发重新渲染。

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

答案 7 :(得分:1)

经过大量搜索和寻找真实的答案之后,我终于得到了我认为是最好的答案:

       <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.ID} 在我改变这个之后,它就像魅力一样工作 我希望这对某人有帮助。

答案 8 :(得分:0)

const [itemSelected, setItemSelected] = setState(null);
....
const FlatListItem = (item) => {
    return (
        <TouchableOpacity onPress={() => setItemSelected(item.id)}>
            <View style={ (itemSelected === item.id) ? style.itemWrapperActive : style.itemWrapper }>
                <Text>{ item.label }</Text>
            </View>
        </TouchableOpacity>
    )
}
....
<FlatList
    ItemSeparatorComponent={() => <View style={{ width: 20 }} />}
    data={ flatListData }
    renderItem={ ({item}) => FlatListItem(item) }
    keyExtractor={ (item) => item.id }
    extraData={ itemSelected }
/>

答案 9 :(得分:0)

我正在使用功能组件,因为我正在使用带有 redux 数据的 Flatlist。 我正在使用 Redux 商店管理所有状态。 这里是api调用后更新Flatlist数据的解决方法。

我第一次是这样做的:-

public class UserDao {
    
    private Connection con;

    public UserDao(Connection con) {
        this.con = con;
    }
    
    // method to insert data of user in database
    
    public boolean saveUser(User user)
    {
        boolean f=false;
        try {
            
             String query = "insert into user(name,email,password,gender,about) values(?,?,?,?,?)";
             PreparedStatement pstmt = this.con.prepareStatement(query);
             pstmt.setString(1, user.getName());
             pstmt.setString(2, user.getEmail());
             pstmt.setString(3, user.getPassword());
             pstmt.setString(4, user.getGender());
             pstmt.setString(5, user.getAbout());
             
             pstmt.executeUpdate();
             f=true;
             
        } catch (Exception e) 
        {
            e.printStackTrace();
        }
        return f;
    }
    
    // Get User by User E-Mail & Password
    
    public User getUserByEmailAndPassword(String email,String password)
    {
      User user=null;
      
      
        try {
            String query ="select * from user Where email=?,password=?";
            PreparedStatement pstmt = con.prepareStatement(query);
            pstmt.setString(1, email);
            pstmt.setString(2, password);
            
            ResultSet set =pstmt.executeQuery();
            
            if(set.next())
            {
                user = new User();
             // Data From DB   
            String name = set.getString("name");
            //  Set in User Obj
            user.setName(name);
            
            user.setId(set.getInt("id"));
            user.setEmail(set.getString("email"));
            user.setPassword(set.getString("[password"));
            user.setGender(set.getString("gender"));
            user.setAbout(set.getString("about"));
            user.setDateTime(set.getTimestamp("regdate")); 
            user.setProfile(set.getString("profile"));
            
            }
           } catch (Exception e) {
            e.printStackTrace();
        }
      
      
        return user;
      
    }
    
}

但数据根本没有重新渲染我的 Flatlist 数据。

作为我喜欢的解决方案如下:-

const DATA  = useSelector((state) => state.address.address);


<FlatList
    style = {styles.myAddressList}
    data = {DATA}
    renderItem = {renderItem}
    keyExtractor = {item => item._id}
    ListEmptyComponent = {EmptyList}
    ItemSeparatorComponent={SeparatorWhite}
    extraData = {refresh}
    
    />

我将 Redux 状态直接传递给 Flatlist 数据源,而不是将其分配给变量。

谢谢。

答案 10 :(得分:0)

在此示例中,要强制重新渲染,只需更改变量machine

const [selected, setSelected] = useState(machine)

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

答案 11 :(得分:0)

在react-native-flatlist中,它们是称为ExtraData的属性。将以下行添加到您的单位列表中。

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

答案 12 :(得分:0)

只需使用:

onRefresh={true}

flatList组件内部。

答案 13 :(得分:0)

如果我们希望FlatList 了解道具和州的数据更改,我们可以构造一个同时引用道具和状态的对象并刷新该公寓表。

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

文档:https://facebook.github.io/react-native/docs/flatlist#extradata

答案 14 :(得分:0)

通过您在extraData

上的交互来更改变量

您可以发挥创造力。

例如,如果您正在处理带有复选框的更改列表。

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

答案 15 :(得分: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 });
    }
  }
}

答案 16 :(得分: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,
}]

答案 17 :(得分:-1)

Flatlist的extraData对我不起作用,我碰巧正在使用redux的道具。这听起来与ED209答复中的评论类似。收到道具后,我最终手动调用了setState。

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