如何让我的删除按钮连续多次从状态中删除项目?

How can I get my delete button to remove items from state more than once consecutively?

抱歉措辞混乱,但我会尽力解释。这是相关的代码块。这个想法是接受键盘输入,并将其添加到保存在状态中的数组中。它部分起作用,因为当我单击一个键时,它会添加到状态数组中。当我单击删除时,它通过复制数组删除最后一项,删除最后一项,然后覆盖整个原始状态。

问题来了。如果再次单击删除,则不会发生任何事情。我猜它与 react 而不是重新渲染有关,但我是个菜鸟所以 idk.

这里有一个 link 到 expo 上的项目,看它的价值(你显然看不到控制台日志)。抱歉鲜艳的颜色,帮助我的菜鸟大脑把事情分开。 https://expo.dev/@qtheginger/projects/Wordley

任何帮助将不胜感激,谢谢!

import React, { useState, useContext } from "react";
import { View, Text, Pressable, StyleSheet, Alert } from "react-native";
import Key from "./Key.js";
import KeyName from "../data/KeyName.json";

import { GameContext } from "../util/gameContext.js";

const styles = StyleSheet.create({
  keyBoard: {
    flex: 1,
    justifyContent: "space-around",
  },
  keyBoardLine: {
    flex: 1,
    flexDirection: "row",
    justifyContent: "space-around",
    // height: "80%",
  },
});

export default () => {
  const { keyVal, setKeyVal } = useContext(GameContext);
  const { cardVal, setCardVal } = useContext(GameContext);
  let rowOne = [];
  let rowTwo = [];
  let rowThree = [];
  
  const keyValSetter = (keyName) => {
    setKeyVal(keyName);
  };
  const cardValSetter = (keyName) => {
    setCardVal([...cardVal, keyName]);
  };
  const combiner = (keyName) => {
    keyValSetter(keyName);
    if (keyName !== "Delete") {
      cardValSetter(keyName);
    } else {
      const newArr = cardVal;
      newArr.pop();
      setCardVal(newArr);
    }
  };
  // loop through keyName to display keyboard
  for (let i = 0; i < KeyName.length; i++) {
    x = i;
    if (i < 10) {
      rowOne.push(
        <Key onPress={() => combiner(KeyName[i])} key={i} index={i} />
      );
    } else if (i === 10 || i < 19) {
      rowTwo.push(
        <Key onPress={() => combiner(KeyName[i])} key={i} index={i} />
      );
    } else {
      rowThree.push(
        <Key onPress={() => combiner(KeyName[i])} key={i} index={i} />
      );
    }
  }
  console.log(keyVal);
  console.log(cardVal);
  return (
    <>
      <View style={styles.keyBoard}>
        <View style={styles.keyBoardLine}>{rowOne}</View>
        <View style={styles.keyBoardLine}>{rowTwo}</View>
        <View style={styles.keyBoardLine}>{rowThree}</View>
      </View>
    </>
  );
};

是的,当从状态中删除时,您正在改变它而不是返回一个新数组。

const { cardVal, setCardVal } = useContext(GameContext);

...

const combiner = (keyName) => {
  keyValSetter(keyName);
  if (keyName !== "Delete") {
    cardValSetter(keyName);
  } else {
    const newArr = cardVal; // <-- reference to state
    newArr.pop();           // <-- mutation!!
    setCardVal(newArr);     // <-- state reference back into state
  }
};

cardVal 状态似乎从来都不是更新的数组引用。由于状态引用从未改变,因此 React 假定状态仍然相同并且不会触发重新渲染。

使用功能状态更新从以前的状态正确更新(而不是范围内关闭的任何状态),并将状态浅复制到新的数组引用中。

示例:

const combiner = (keyName) => {
  keyValSetter(keyName);
  if (keyName !== "Delete") {
    cardValSetter(keyName);
  } else {
    setCardVal(cards => cards.slice(0, -1)) // <-- copy all but last element
  }
};

同样,cardValSetter 也应该使用功能状态更新来更新以前的状态。

const cardValSetter = (keyName) => {
  setCardVal(cardVal => [...cardVal, keyName]);
};