Flatlist 不显示来自 useContext 的列表

Flatlist doesn't display the list from useContext

在 React Native 应用程序中,我有一个主屏幕和一个辅助屏幕,用户可以使用它们添加应该在主屏幕上显示的项目。我正在使用上下文来保存项目列表。问题是当我将项目添加到第二个屏幕并转到主屏幕时。显示的列表是空的。

任何帮助解释为什么会发生这种情况以及如何处理它?这是 数据上下文 export const ExpenseContext = createContext();

App.js

const Stack = createNativeStackNavigator();
function App() {
  const [expenseList, setExpenseList] = useState([]);
  return (
    <NavigationContainer>
      <ExpenseContext.Provider value={{ expenseList, setExpenseList }}>
        <Stack.Navigator>
          <Stack.Screen
            name="Home"
            component={Home}
            options={{ title: "Dashboard" }}
          />
          <Stack.Screen
            name="AddItem"
            component={AddItem}
            options={{ title: "CashFlowCreate" }}
          />
        </Stack.Navigator>
      </ExpenseContext.Provider>
    </NavigationContainer>
  );
}
export default App;

Home.js

function Home({ route, navigation }) {
  const { expenseList } = useContext(ExpenseContext);
  return (
    <View style={styles.container}>
      <Text style={styles.text}>Budget:</Text>
      <Button title="+" onPress={() => navigation.navigate("AddItem")} />
      <View>
        <FlatList
          style={styles.listContainer}
          data={expenseList}
          renderItem={(data) => <Text>{data.item.name}</Text>}
        />
      </View>
    </View>
  );
}
export default Home;

AddItem.js

function AddItem({ navigation }) {
  const { expenseList, setExpenseList } = useContext(ExpenseContext);
  const [name, setName] = useState("");
  const [amount, setAmount] = useState("");
  const itemsList = expenseList;
  return (
    <View style={styles.container}>
      <TextInput
        style={styles.input}
        onChangeText={(name) => setName( name )}
        value={name}
        placeholder="Name"
        keyboardType="default"
      />
      {name === "" && (
        <Text style={{ color: "red", fontSize: 12, paddingLeft: 12 }}>
          Name is required
        </Text>
      )}
      <TextInput
        style={styles.input}
        onChangeText={(amount) => setAmount( amount )}
        value={amount}
        placeholder="Amount"
        keyboardType="numeric"
      />
      {amount === "" && (
        <Text style={{ color: "red", fontSize: 12, paddingLeft: 12 }}>
          Amount is required
        </Text>
      )}
      
      <Button
        title="Add"
        style={styles.btn}
        onPress={() => {
          if (name === "" || amount === "") {
            alert("Please Enter the required values.");
          } else {
            itemsList.push({
              name: name,
              amount: amount,
            });
            setExpenseList(itemsList);
          }
        }}
      />
      <Button
        title="View Dashboard"
        style={styles.btn}
        onPress={() => {
          navigation.navigate("Home");
        }}
      />
    </View>
  );
}

export default AddItem;

您的代码中存在多个方面的问题。我能看到的一个问题在 AddItem 中。当你设置:

const itemsList = expenseList

我认为你这样做是为了:

itemsList.push({
  name: name,
  amount: amount,
});

但你应该看看 spread operator 并尝试:

setExpenseList(...expenseList, {
  name,
  amount,
})

重写 AddItem.js:

function AddItem({ navigation }) {
  const { expenseList, setExpenseList } = useContext(ExpenseContext)
  const [name, setName] = useState('')
  const [amount, setAmount] = useState('')

  return (
    <View style={styles.container}>
      <TextInput style={styles.input} onChangeText={setName} value={name} placeholder='Name' keyboardType='default' />
      {name === '' ? <Text style={styles.err}>Name is required</Text> : null}
      <TextInput style={styles.input} onChangeText={setAmount} value={amount} placeholder='Amount' keyboardType='numeric' />
      {amount === '' ? <Text style={styles.err}>Amount is required</Text> : null}

      <Button
        title='Add'
        style={styles.btn}
        onPress={() => {
          name === '' || amount === ''
            ? alert('Please Enter the required values.')
            : setExpenseList(...expenseList, {
                name: name,
                amount: amount,
              })
        }}
      />
      <Button title='View Dashboard' style={styles.btn} onPress={() => navigation.navigate('Home')} />
    </View>
  )
}

export default AddItem

在你的 Home.js 你的 FlatList 它缺少 keyExtractor 而你正试图声明 [=18= 的道具] 在 <Text> 之外,重写:

function Home({ navigation }) {
  const { expenseList } = useContext(ExpenseContext);

  return (
    <View style={styles.container}>
      <Text style={styles.text}>Budget:</Text>
      <Button title="+" onPress={() => navigation.navigate("AddItem")} />
      <View>
        <FlatList
          style={styles.listContainer}
          data={expenseList}
          keyExtractor={(_,key) => key.toString()}
          renderItem={(data) => <Text>{data.item.name}</Text>}
        />
      </View>
    </View>
  );
}
export default Home;

编辑:

正在回答 。我对文档的理解是不正确的,因为 keyExtractor 用于识别 id 并通过您的注释代码,除非您传递给 FlatList 的数据具有 [=23] 的 属性 =] 那么那是行不通的。

此外,如果 key 不是字符串,则应为:

keyExtractor={(item) => item.key.toString()}

我解决了,在AddItem组件中删除const itemsList = expenseList;和onPress添加按钮应该是这样的

 onPress={() => {
          name === "" || amount === ""
            ? alert("Please Enter the required values.")
            : setExpenseList([
                ...expenseList,
                {
                  key:
                    Date.now().toString(36) +
                    Math.random().toString(36).substr(2),
                  name: name,
                  amount: amount,
                },
              ]);
        }}

我添加了密钥,因为稍后需要。