[英]TypeError: undefined is not a function (near '...todos.map...')
I am trying to use ASyncStorage inside of the useState hook to load data from storage if present.我试图在 useState 钩子内使用 ASyncStorage 从存储加载数据(如果存在)。 I am rendering the todos inside a map function but before that I am checking whether todos is undefined or [].我在 map 函数中渲染 todos,但在此之前我正在检查 todos 是 undefined 还是 []。 The logic should be returning [] to useState if the data is not present but it is giving undefined!如果数据不存在,逻辑应该返回 [] 到 useState 但它给出 undefined!
Here is an image of the error这是错误的图像
Here is the code:这是代码:
export default function App() {
const [todo, setTodo] = useState('');
const [todos, setTodos] = useState(async () => {
try {
const value = await AsyncStorage.getItem('@MySuperStore:key');
// We have data!!
return value ? JSON.parse(value) : [];
} catch (error) {
// Error retrieving data
console.log(error);
}
});
const addItem = (newTodo) => {
if (newTodo.length === 0) {
Alert.alert(
'Enter a String',
'You have entered a string with 0 characters',
[{ text: 'Okay', style: 'default' }]
);
} else {
console.log(newTodo);
let newTodos = [newTodo, ...todos];
setTodo('');
_storeData(newTodos).then(_retrieveData());
// setTodos(newTodos);
}
};
const deleteTodo = (idx) => {
setTodos(todos.filter((todo, id) => id !== idx));
};
const _storeData = async (value) => {
try {
await AsyncStorage.setItem('@MySuperStore:key', JSON.stringify(value));
} catch (error) {
// Error saving data
console.log(error);
}
};
const _retrieveData = async () => {
try {
const value = await AsyncStorage.getItem('@MySuperStore:key');
if (value !== null) {
// We have data!!
setTodos(JSON.parse(value));
console.log(value);
}
} catch (error) {
// Error retrieving data
console.log(error);
}
};
return (
<TouchableWithoutFeedback
onPress={() => {
Keyboard.dismiss();
}}
>
<View style={styles.outerContainer}>
<Text style={styles.header}>TODO</Text>
<View style={styles.container}>
<TextInput
placeholder='new todo'
style={styles.input}
value={todo}
onChangeText={(text) => {
setTodo(text);
}}
></TextInput>
<Button title='Add' onPress={() => addItem(todo)}></Button>
</View>
<ScrollView style={styles.scrollView}>
{todos === [] || todos === undefined ? (
<View>
<Text>Add a todo!</Text>
</View>
) : (
todos.map((todo, idx) => (
<View style={styles.todo} key={idx}>
<Text style={styles.todoText}>{todo}</Text>
<View style={styles.delete}>
<Button
color='red'
title='Delete'
onPress={() => deleteTodo(idx)}
></Button>
</View>
</View>
))
)}
</ScrollView>
</View>
</TouchableWithoutFeedback>
);
}
I'm not sure why the default state of todos
would use an async function, that doesn't make sense to me.我不确定为什么todos
的默认状态会使用 async 函数,这对我来说没有意义。 Instead I would do const [todos, setTodos] = useState([]);
相反,我会做const [todos, setTodos] = useState([]);
and leverage useEffect
hook something similar to this:并利用useEffect
钩子类似于以下内容:
useEffect(() => {
(async () => {
try {
const value = await AsyncStorage.getItem('@MySuperStore:key');
// We have data!!
setTodos(value ? JSON.parse(value) : [])
} catch (error) {
// Error retrieving data
console.log(error);
}
})();
},[]);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.