React Native Flatlist 多选不更新

React native flatlist multiple selection is not updating

我正在使用平面列表来公开我保存在数据库中的所有成分列表,但是一旦我更新状态,它就不会反映在平面列表组件上。

平面列表组件

<FlatList
  horizontal
  bounces={false}
  key={ingredientList.id}
  data={ingredientList}
  renderItem={({ item }) => (
    <TouchableOpacity onPress={() => selectedIngredient(item)}>
      <Card key={item.id}>
        <Text key={item.title} style={styles.titleText}>{item.name}</Text>
        <Text key={item.title} style={styles.titleText}>{item.isSelected?'selected':'not selected'} 
        </Text>
        <ImageBackground key={item.illustration} source={item.illustration} style={styles.cardImage}> 
        </ImageBackground>
      </Card>
    </TouchableOpacity>
  )}
  keyExtractor={(item) => item.index}
/>

这是找到所选项目“selectedIngredient”的函数

function selectedIngredient(item) {
    console.log('received: ', item.name)
    item.isSelected = !item.isSelected;
    return { ...item.isSelected }
}

当我尝试在“item.isSelected = !item.isSelected”之后使用 console.log 进行调试时,该组件调用正在运行,但 IU 未更新。有人可以帮助我了解如何修复它吗?

您需要在 class-based 组件中使用 setState 或在功能组件中使用 useState 挂钩来设置状态。

function selectedIngredient(item) {
    console.log('received: ', item.name)
    item.isSelected = !item.isSelected; //this is not how you set state
    return { ...item.isSelected }
}

截图:

这是我根据您当前的情况修改的旧示例:

import React, { useState } from 'react';
import {
  Text,
  View,
  StyleSheet,
  FlatList,
  TouchableOpacity,
} from 'react-native';
import Constants from 'expo-constants';

// You can import from local files

// or any pure javascript modules available in npm

const ingredientList = [
  {
    id: 1,
    name: 'item1',
    selected: false,
  },
  {
    id: 2,
    name: 'item 2',
    selected: false,
  },
  {
    id: 3,
    name: 'item 3',
    selected: false,
  },
  {
    id: 8,
    name: 'item 4',
    selected: false,
  },
  {
    id: 4,
    name: 'item 5',
    selected: false,
  },
  {
    id: 5,
    name: 'item 6',
    selected: false,
  },
];

export default function App() {
  const [selectedItem, setSelectedItem] = useState(null);
  const [allItems, setAllItems] = useState(ingredientList);

  const selectedIngredient = (item) => {
    console.log('selecionado: ' + item.name);
    setSelectedItem(item);
    /* Below operation can be improved by passing index to the function itself.
       so filtering would not be required
     */
    let temp = allItems.filter((parentItem) => parentItem.id !== item.id);
    item.selected = !item.selected;
    temp = temp.concat(item);
    temp.sort((a, b) => parseInt(a.id) - parseInt(b.id));
    setAllItems(temp);
    console.log(allItems);
  };
  return (
    <View style={styles.container}>
      <FlatList
        style={styles.flatlist}
        horizontal
        bounces={false}
        data={allItems}
        renderItem={({ item }) => (
          <TouchableOpacity
            style={styles.flatListItem}
            key={item.id}
            onPress={() => selectedIngredient(item)}>
            <Text>{item.name}</Text>
            {!item.selected ? (
              <Text style={{ color: 'red' }}>{'Not Selected'}</Text>
            ) : (
              <Text style={{ color: 'green' }}>{'Selected'}</Text>
            )}
          </TouchableOpacity>
        )}
        keyExtractor={(item) => item.index}
      />

      {selectedItem ? (
        <View style={styles.selectedTextView}>
          <Text style={styles.selectedText}>{`${selectedItem.name} ${
            selectedItem.selected ? 'selected' : 'not selected'
          }`}</Text>
        </View>
      ) : (
        <View style={styles.selectedTextView}>
          <Text style={styles.selectedText}>{`Nothing selected`}</Text>
        </View>
      )}
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    paddingTop: Constants.statusBarHeight,
    backgroundColor: '#ecf0f1',
    padding: 8,
  },
  flatListItem: {
    width: 100,
    height: 100,
    backgroundColor: 'white',
    margin: 5,
    borderRadius: 10,
    justifyContent: 'center',
    alignItems: 'center',
  },
  selectedTextView: {
    flex: 8,
    backgroundColor: 'white',
    margin: 5,
    borderRadius: 10,
    justifyContent: 'center',
    alignItems: 'center',
    fontSize: 20,
  },
  selectedText: {
    fontSize: 30,
  },
});

Live Demo