해결된 질문
작성
·
1.1K
·
수정됨
1
const [editText, setEditText] = useState("");
const addToDo = async () => {
if (text === "") {
return;
}
const newToDos = {
...toDos,
[Date.now()]: { text, working, done: false, isEdit: false }
};
setToDos(newToDos);
await saveToDos(newToDos);
setText("");
};
const edit = (key) => {
const newTodos = [...toDos];
newTodos[key].isEdit = !newTodos[key].isEdit;
setTodos(newTodos);
};
const editToDos = (key) => {
const newTodos = [...toDos];
newTodos[key].text = editText;
newTodos[key].isEdit = false;
setTodos(newTodos);
seteditText("");
};
{toDos[key].isEdit ? (
<TextInput
style={styles.editInput}
onSubmitEditing={() => editToDos(key)}
defaultValue={toDos[key].text}
onChangeText={setEditText}
returnKeyType="done"
/>) : (
<Text
style={
toDos[key].done
? {
...styles.toDoText,
textDecorationLine: "line-through",
}
: styles.toDoText
}
>
{toDos[key].text}
</Text>
)
}
<TouchableOpacity onPress={() => edit(key)}>
<AntDesign name="edit" size={24} color="white" />
</TouchableOpacity>
<TouchableOpacity onPress={() => deleteToDo(key)}>
<Fontisto name="trash" size={18} color={theme.grey} />
</TouchableOpacity>
</View>
) : null
)}
</ScrollView>
편집버튼을 누르면 edit함수를 실행시켜 isEdit을 true로 바꿔 편집을 하는 기능을 만들고 있습니다.
첫번째 문제는 원래 있던 todo의 text와 똑같은, 편집에 대한 textinput의 text가 떠있습니다.
그리고 원래는 편집 버튼을 누르면 오른쪽에 있는 편집에 대한 text에 textinput 창이 띄워지고
왼쪽에 있는 text는 그대로 있는 상태에서 done을 눌러도 오류가 떴었구요.
코드를 좀 수정했더니 지금은 편집버튼을 누르기만 해도
TypeError: Invalid attempt to spread non-iterable instance.
In order to be iterable, non-array objects must have a [Symbol.iterator]() method., js engine: hermes
이러한 오류가 발생합니다.
deletetodo는 제대로 작동하고 있습니다.
어디가 문제인걸까요 ..ㅠ
아래는 import 와 style 에 관한 코딩을 제외한 전문입니다.
export default function App() {
const [working, setWorking] = useState(true);
const [text, setText] = useState("");
const [toDos, setToDos] = useState({});
const [editText, setEditText] = useState("");
useEffect(() => {
loadToDos();
loadMode();
}, []);
const travel = () => {
setWorking(false)
saveMode(false)
};
const work = () => {
setWorking(true)
saveMode(true)
};
const edit = (key) => {
const newTodos = [...toDos];
newTodos[key].isEdit = !newTodos[key].isEdit;
setTodos(newTodos);
};
const editToDos = (key) => {
const newTodos = [...toDos];
newTodos[key].text = editText;
newTodos[key].isEdit = false;
setTodos(newTodos);
seteditText("");
};
const onChangeText = (payload) => setText(payload);
const saveMode = async(mode) => {
try {
await AsyncStorage.setItem("@mode",JSON.stringify(mode))
} catch(error) {
console.log(error);
}
};
const loadMode = async () => {
const m = await AsyncStorage.getItem("@mode")
setWorking(JSON.parse(m))
};
const saveToDos = async (newToDos) => {
try {
await AsyncStorage.setItem(STORAGE_KEY, JSON.stringify(newToDos));
} catch(e) { alert("Error!")
}
};
const loadToDos = async () => {
const s = await AsyncStorage.getItem(STORAGE_KEY);
console.log(s);
setToDos(JSON.parse(s))
};
const addToDo = async () => {
if (text === "") {
return;
}
const newToDos = {
...toDos,
[Date.now()]: { text, working, done: false, isEdit: false }
};
setToDos(newToDos);
await saveToDos(newToDos);
setText("");
};
const changeDone = async (key) => {
const newToDos = {
...toDos,
[key]: { ...toDos[key], done: !toDos[key].done },
};
setToDos(newToDos);
await saveToDos(newToDos);
};
const deleteToDo = (key) => {
Alert.alert("Delete To Do", "Are you sure?", [
{ text: "Cancel" },
{
text: "I'm Sure",
style: "destructive",
onPress: () => {
const newToDos = { ...toDos };
delete newToDos[key];
setToDos(newToDos);
saveToDos(newToDos);
},
},
]);
};
return (
<View style={styles.container}>
<StatusBar style="auto" />
<View style={styles.header}>
<TouchableOpacity onPress={work}>
<Text
style={{ ...styles.btnText, color: working ? "white" : theme.grey }}
>
Work
</Text>
</TouchableOpacity>
<TouchableOpacity onPress={travel}>
<Text
style={{
...styles.btnText,
color: !working ? "white" : theme.grey,
}}
>
Travel
</Text>
</TouchableOpacity>
</View>
<TextInput
onSubmitEditing={addToDo}
onChangeText={onChangeText}
returnKeyType="done"
value={text}
placeholder={
working ? "What do you have to do?" : "Where do you want to go?"
}
style={styles.input}
/>
<ScrollView>
{Object.keys(toDos).map((key) =>
toDos[key].working === working ? (
<View style={styles.toDo} key={key}>
{toDos[key].done ? (
<TouchableOpacity onPress={() => changeDone(key)}>
<Fontisto
name="checkbox-active"
size={18}
color="red"
/>
</TouchableOpacity>
) : (
<TouchableOpacity onPress={() => changeDone(key)}>
<Fontisto
name="checkbox-passive"
size={18}
color={theme.grey}
/>
</TouchableOpacity>
)}
<Text style={styles.toDoText}>{toDos[key].text}</Text>
{toDos[key].isEdit ? (
<TextInput
style={styles.editInput}
onSubmitEditing={() => editToDos(key)}
defaultValue={toDos[key].text}
onChangeText={setEditText}
returnKeyType="done"
/>) : (
<Text
style={
toDos[key].done
? {
...styles.toDoText,
textDecorationLine: "line-through",
}
: styles.toDoText
}
>
{toDos[key].text}
</Text>
)
}
<TouchableOpacity onPress={() => edit(key)}>
<AntDesign name="edit" size={24} color="white" />
</TouchableOpacity>
<TouchableOpacity onPress={() => deleteToDo(key)}>
<Fontisto name="trash" size={18} color={theme.grey} />
</TouchableOpacity>
</View>
) : null
)}
</ScrollView>
</View>
);
}
답변 1
1
안녕하세요, 인프런 AI 인턴입니다.
김수환님의 문제를 살펴보니 TypeError: Invalid attempt to spread non-iterable instance.
오류는 스프레드 구문을 사용할 때 해당되는 객체가 반복 가능한(iterable) 객체가 아닐 때 발생합니다. JavaScript에서는 배열이 반복 가능한 객체입니다.
제시해주신 코드에서 오류가 발생하는 부분은 const newTodos = [...toDos];
와 같이 toDos
를 배열로 취급하여 스프레드하려고 시도한 부분입니다. 하지만 toDos
는 {}
로 초기화되어 있어 객체이며, 이를 배열로 스프레드할 수 없습니다.
해결을 위해서는 toDos
객체 내에 있는 특정 키의 값을 수정하는 방법을 사용해야 합니다. 수정된 코드는 아래와 같이 될 것입니다:
const edit = (key) => {
const newTodos = {
...toDos,
[key]: { ...toDos[key], isEdit: !toDos[key].isEdit }
};
setToDos(newTodos);
};
const editToDos = (key) => {
const newTodos = {
...toDos,
[key]: { ...toDos[key], text: editText, isEdit: false }
};
setToDos(newTodos);
setEditText("");
};
setToDos
함수를 사용하여 toDos
상태를 업데이트할 때, 각 키에 대응하는 객체의 프로퍼티만 수정하고 있습니다. 이렇게 수정하면 비구조화 할당을 배열이 아닌 객체에 적절하게 사용할 수 있으므로 위에서 언급된 오류가 해결될 것입니다.
추가적으로, 코드에 setTodos
라는 오타가 있습니다. setToDos
를 올바르게 사용해야 합니다.
코드를 수정해서 다시 시도해보시기 바랍니다.