React / TypeScript使用setState()更新数组时出错



我希望使用从setState返回的更新器修改数组中一个项目的属性。这个函数作为props传递给子节点,然后子节点用自己的索引调用这个函数来改变自己的状态。

const tryMarkHabitAsComplete = (index: number) => {
let list: HabitType[] = [...habitList];
let habit = {
...list[index],
isComplete: true,
};
list[index] = habit;
setHabitList({list});
};

<strongsetHabitList(list);数组被清除并变为未定义,因此我无法在调用此函数一次后使用它。>

一直出现的错误是:

Argument of type '{ list: HabitType[]; }' is not assignable to parameter of type 'SetStateAction<HabitType[]>'. Object literal may only specify known properties, and 'list' does not exist in type 'SetStateAction<HabitType[]>'

我将状态视为不可变的,并尝试(我认为)设置状态。在调试时,每次我点击我清空我的habitsList数组。进一步,我将状态定义为:

const [habitList, setHabitList] = useState<HabitType[]>([]);

如果我尝试以其他方式setState,数组将变为未定义或空白并丢失信息。我应该澄清一下,这是一个用/react-native编写的业余项目。

绝笔编辑:

react-native应用中的2个组件,抛弃了CSS &无关紧要的进口:Chain.tsx

export type HabitType = {
text: string;
index: number;
isComplete: boolean;
tryMarkHabit: (index: number) => void;
};
const Chain = (props: any) => {
const [habitList, setHabitList] = useState<HabitType[]>([]);
// Set the initial state once w/ dummy values
useEffect(() => {
setHabitList([
{
text: "1",
index: 0,
isComplete: false,
tryMarkHabit: tryMarkHabitAsComplete,
},
{
text: "2",
index: 1,
isComplete: false,
tryMarkHabit: tryMarkHabitAsComplete,
}
]);
}, []);
// Only is previous item is complete, let habit be marked as complete
const tryMarkHabitAsComplete = (index: number) => {
let list: HabitType[] = [...habitList];
let habit = {
...list[index],
isComplete: true,
};
list[index] = habit;
setHabitList(list);
};
let habitKeyCount = 0;
return (
<View style={styles.container}>
{habitList.map((habit) => (
<Habit key={habitKeyCount++} {...habit} />
))}
</View>
);
};
export default Chain;

Habit.tsx

import { HabitType } from "./Chain";
const Habit = ({ text, index, isComplete, tryMarkHabit }: HabitType) => {
const [complete, setComplete] = useState<boolean>(false);
return (
<TouchableOpacity
style={complete ? styles.completeHabit : styles.uncompleteHabit}
onPress={() => tryMarkHabit(index)}
>
<Text style={styles.chainText}>{text}</Text>
</TouchableOpacity>
);
};
export default Habit;

当我按下一个习惯时,它成功地调用tryMarkHabitAsComplete,但是它似乎清除了数组-据我所知,数组之后变得未定义。

Issue

如果我不得不猜测,我会说你在回调中有一个陈旧的habitList状态的外壳,它本身就是你状态中的一个陈旧的外壳。

<标题>

解决方案我建议在处理程序中使用功能状态更新。功能更新允许从以前的状态更新状态,而不是从更新进入队列的呈现周期更新状态。这是一个细微但重要的区别。

我还建议不要将处理程序包含在封闭状态中。只需将其作为普通回调传递给Habit,这样您就可以避免任何陈旧的附件。

const Chain = (props: any) => {
const [habitList, setHabitList] = useState<HabitType[]>([]);
// Set the initial state once w/ dummy values
useEffect(() => {
setHabitList([
{
text: "1",
index: 0,
isComplete: false,
},
{
text: "2",
index: 1,
isComplete: false,
}
]);
}, []);
// Only is previous item is complete, let habit be marked as complete
const tryMarkHabitAsComplete = (index: number) => {
setHabitList(list => list.map((habit, i) => i === index ? {
...habit,
isComplete: true,
} : habit);
};
let habitKeyCount = 0;
return (
<View style={styles.container}>
{habitList.map((habit) => (
<Habit
key={habitKeyCount++}
{...habit}
tryMarkHabit={tryMarkHabitAsComplete}
/>
))}
</View>
);
};

编辑isComplete样式

Habit应该只使用传递的isCompleteprop来设置所需的CSS样式。

const Habit = ({ text, index, isComplete, tryMarkHabit }: HabitType) => {
return (
<TouchableOpacity
style={isComplete ? styles.completeHabit : styles.uncompleteHabit}
onPress={() => tryMarkHabit(index)}
>
<Text style={styles.chainText}>{text}</Text>
</TouchableOpacity>
);
};

最新更新