React本机useState更新,即使它还没有被调用



所以我用react native做了一些相当简单的事情。我有一个函数,它创建了一个状态的副本,最初是一个数组,然后我更新副本,然后我最终调用我的setState来更新原始数组。然而,当我对副本进行变异时,出于某种奇怪的原因,即使我不调用setState,它也会从状态变异数组。我尝试了所有我认为可以修复它的方法,使用切片,[…复制],剪接,什么都没有,它仍然会变异,为什么,我只是不明白它为什么会变异?如果有人能帮助我,我将不胜感激。

这是的功能

function completeTaskHandler(goalName, taskId, taskIndex, updateAction) {
const taskSnapShot = tasks.slice();
console.log(taskSnapShot);//logs the copy
console.log(tasks);// logs the original array
taskSnapShot[taskIndex].isComplete = "true";
console.log(taskSnapShot);//results in mutated array
console.log(tasks);//Also results in mutated array why??
};

这是完整的代码块

import React, { useState } from "react";
import { View, StyleSheet, TouchableOpacity } from "react-native";
import { HeaderButtons, Item } from "react-navigation-header-buttons";
import { useSelector, useDispatch } from "react-redux";
import { Ionicons } from "@expo/vector-icons";
//Custom Components
import Task from "../../components/local/goals/EditGoalTask";
//Header Custom Component
import CustomBackButton from "../../components/HeaderButtonDark";
//Controllers
import { DefaultText, SmallText, HeaderText, SmallTextItalic } from "../../controllers/TextController";
//Constants
import Colors from "../../constants/Colors";
//Redux reducers
import { udpateTask } from "../../store/actions/user";
const EditGoal = ({ navigation, route }) => {
//Initialize variables
const dispatch = useDispatch();
const { goalId, goalNameFromAddPage } = route.params;
let selectedGoal = useSelector(state => state.userReducer.goals.find((goal) => goal.id === goalId));
if (goalNameFromAddPage) {
selectedGoal = useSelector(state => state.userReducer.goals.find((goal) => goal.goalName === goalNameFromAddPage));
}
//Deconstruct needed variables
const { goalName, startDate, status, tasksArrayOfObjects } = selectedGoal;
//Initialize States
const [tasks, setTasks]= useState(tasksArrayOfObjects.fitler((task) => {
if (!task.isComplete) {
return true;
} else {
return false;
}
}));
//Methods
function deleteTaskHandler(goalName, taskId, taskIndex, updateAction) {
const taskSnapShot = [...tasks];
taskSnapShot.splice(taskIndex, 1);
setTasks(taskSnapShot);
//dispatch(udpateTask(goalName, taskId, updateAction));
};
/* Has issues */
function completeTaskHandler(goalName, taskId, taskIndex, updateAction) {
const taskSnapShot = tasks.slice();
console.log(taskSnapShot);
console.log(tasks);
taskSnapShot[taskIndex].isComplete = "true";
console.log(taskSnapShot);
console.log(tasks);
/*
function copyArray(arr) {
const arrCopy = arr.slice();
const copy = arrCopy.splice(0, arrCopy.length);
return copy;
}
console.log(tasks);
const taskSnapShot = copyArray(tasks);
taskSnapShot[taskIndex].isComplete = true;
console.log(taskSnapShot);
console.log(tasks);
*/
//dispatch(udpateTask(goalName, taskId, updateAction));
};

navigation.setOptions({
headerLeft: () => (
<HeaderButtons HeaderButtonComponent={CustomBackButton}>
<Item 
title="BACK" 
iconName="md-close"
onPress={() => navigation.popToTop()}
/>
</HeaderButtons>
),
});

return(
<View style={styles.screen}>
<View style={styles.header}>
<View style={styles.goalContainer}>
<SmallText>Goal:</SmallText>
<HeaderText>{goalName}</HeaderText>
</View>
<View style={styles.goalStatusContainer}>
<SmallText style={styles.headerTextMargin}>Started: {startDate}</SmallText>
<View style={{ flexDirection: "row" }}>
<SmallText>Finished: </SmallText>
<SmallTextItalic>{status}</SmallTextItalic>
</View>
</View>
</View>
<View style={styles.pageDescription}>
<DefaultText>
Here is where you can add, delete, or track the steps you need to do in
order to achieve your goal.
</DefaultText>
</View>
<View style={styles.taskContainer}>
{tasks.map((task, index) => {
return <Task 
title={task.taskName} 
key={"key"+index} 
deleteTask={deleteTaskHandler.bind(this, goalName, task.id, index, "delete")}
completeTask={completeTaskHandler.bind(this, goalName, task.id, index, "complete")}
/>
})}
<View style={styles.touchableContainer}>
<TouchableOpacity onPress={() => alert()}>
<View style={{...styles.task, ...styles.addAStepContainer}}>
<View style={styles.addAStep}>
<Ionicons style={{ marginRight: 5 }} name="ios-add" size={23} color={Colors.grey} /> 
<DefaultText style={{ color: Colors.grey, fontSize: 18 }}>Add a step</DefaultText>
</View>
</View>
</TouchableOpacity>
</View>
</View>
</View>
);
};
const styles = StyleSheet.create({
screen: {
paddingHorizontal: 10,
},
header: {
flexDirection: "row",
height: 80,
//alignItems: 'center', 
},
pageDescription: {
paddingVertical: 10,
},
goalContainer: {
flex: 1,
},
goalStatusContainer: {
flex: 1,
alignItems: "flex-end",
},
headerTextMargin: {
marginBottom: 4,
},
touchableContainer: {
borderRadius: 10,
overflow: "hidden",
},
taskContainer: {
//borderWidth: 1,
},
addAStepContainer: {
paddingVertical: 20,
},
addAStep: {
flexDirection: "row",
},
});
export default EditGoal;

这有点棘手。当你这样做:

const taskSnapShot = tasks.slice();

您创建了一个新的数组,但在该数组中,您不会复制tasks中的对象,而只是引用这些对象。所以基本上,taskSnapShot是一个引用数组。因此,当您在taskSnapShot中修改对象时,也可以在tasks中修改它。

为了解决这个问题,你必须复制你想修改的对象:

const taskSnapShot = [...tasks];
taskSnapShot[taskIndex] = {...taskSnapShot[taskIndex], isComplete: true};

相关内容

  • 没有找到相关文章

最新更新