Javascript 保存多个项目时,异步存储无法正常工作
我有一个主屏幕,您可以在其中看到以卡片形式显示的多个项目。您可以通过按某个项目查看其详细信息来访问该项目。在详细信息屏幕上,我添加了一个书签选项,使用异步存储保存该项目,您还可以在另一个名为savedItems屏幕的屏幕上检查保存的项目 问题是:Javascript 保存多个项目时,异步存储无法正常工作,javascript,reactjs,react-native,Javascript,Reactjs,React Native,我有一个主屏幕,您可以在其中看到以卡片形式显示的多个项目。您可以通过按某个项目查看其详细信息来访问该项目。在详细信息屏幕上,我添加了一个书签选项,使用异步存储保存该项目,您还可以在另一个名为savedItems屏幕的屏幕上检查保存的项目 问题是: 当我为一个项目添加书签时,它会被正确保存,我可以转到savedItems屏幕并在那里找到它,但有时我必须重新加载应用程序才能使该项目显示在savedItems屏幕上,这是为什么 如果我预订了多个项目,它们都会被保存(在console.log上),但
- 当我为一个项目添加书签时,它会被正确保存,我可以转到savedItems屏幕并在那里找到它,但有时我必须重新加载应用程序才能使该项目显示在savedItems屏幕上,这是为什么
- 如果我预订了多个项目,它们都会被保存(在console.log上),但由于某种原因,只有最后一个项目会显示在SavedItems屏幕上,而不会显示超过一个项目
const DetailScreen = (props) => {
const [saved, setSaved] = useState([]);
const [items, setItems] = useState(props.route.params);
const onSave = (item) => {
const newItems = [...saved, item];
setSaved(newItems);
const items = JSON.stringify(newItems);
SaveItem("saved", items).then((res) => {
console.log("saved", res);
});
};
const goToDetails = () => {
setSaved([]);
props.navigation.navigate("SaveScreen");
};
const { width, height } = Dimensions.get("window");
const { data } = props.route.params; // this returns the data from each article
//ReadItem("saved").then((res) => console.log(res));
return (
<TouchableOpacity
...
onPress={() => {
onSave(data);
}}
>
<MaterialCommunityIcons
name="bookmark"
size={35}
color={colors.shade2}
/>
</TouchableOpacity>
)
如果我预订了多个项目,它们都会被保存(在console.log上),但由于某种原因,只有最后一个项目会显示在SavedItems屏幕上,而不会显示超过一个项目
我认为问题在于,当你保存新项目时,你会删除旧项目。装载DetailScreen
时,必须阅读旧项目。或者您可以读取onSave方法中的项。这样更安全。这取决于您的应用程序体系结构
const DetailScreen=(道具)=>{
const[items,setItems]=useState(props.route.params);
const onSave=(项目)=>{
让保存=[];
ReadItem(“已保存”)
。然后((res)=>{
如果(res){
saved=JSON.parse(res);
}
const newItems=[…已保存,项];
const items=JSON.stringify(newItems);
SaveItem(“saved”,items)。然后((res)=>{
console.log(“已保存”,res);
});
})
.catch((e)=>console.warn(e));
};
常数goToDetails=()=>{
储蓄([]);
道具。导航。导航(“保存屏幕”);
};
const{width,height}=Dimensions.get(“窗口”);
const{data}=props.route.params;//返回每个项目的数据
//ReadItem(“已保存”)。然后((res)=>console.log(res));
返回(
{
保存(数据);
}}
>
)
当我为一个项目添加书签时,它会被正确保存,我可以转到savedItems屏幕并在那里找到它,但有时我必须重新加载应用程序才能使该项目显示在savedItems屏幕上,这是为什么
我只知道为什么会这样。在某些情况下,您不会卸载SaveScreen
。当您返回到保存屏幕时
componentDidMount不会被调用。只需尝试将console.log添加到componentDidMount,如果错过console.log,则当您重现此行为时,意味着您未卸载保存屏幕
要处理所有情况,您可以尝试这样做:
导出默认类详细信息扩展组件{
状态={
已保存:[],
};
removeItem=()=>{
删除项目(“已保存”)
。然后((res)=>{
这是我的国家({
已保存:[],
});
控制台日志(res);
})
.catch((e)=>console.log(e));
};
componentDidMount=()=>{
这是readItems();
this.unsubscribe=navigation.addListener('focus',this.readItems);
};
组件将卸载(){
这个。取消订阅();
}
readItems=()=>{
ReadItem(“已保存”)
。然后((res)=>{
如果(res){
const saved=JSON.parse(res);
这是我的国家({
保存:保存,
});
}
})
.catch((e)=>console.warn(e));
}
render(){…}
}
您好,谢谢您的回复,关于我的第一个问题,我不太清楚在哪里以及如何调用usecallback,您能否详细说明一下,我以前从未使用过它们,关于我的问题的第二个回复,我在componentDidMount中添加了一个console.log,当行为完全按照您提到的方式复制时,它被遗漏了,如何卸载保存屏幕。@Felix我已经更新了示例,您如何读取onSave方法中的项。这是最安全的方法如何从路由器上卸载它所依赖的保存屏幕。我认为您像StackNavigator一样打开了保存屏幕,当您不关闭此屏幕并在保存屏幕上再打开一个时,问题就会重现。我建议您收听事件willMount并阅读其中的项目。我会更新我的回答你是个救命恩人,谢谢你的回答。这很清楚,直截了当
export default class Details extends Component {
state = {
saved: [],
};
removeItem = () => {
DeleteItem("saved")
.then((res) => {
this.setState({
saved: [],
});
console.log(res);
})
.catch((e) => console.log(e));
};
componentDidMount = () => {
ReadItem("saved")
.then((res) => {
if (res) {
const saved = JSON.parse(res);
this.setState({
saved: saved,
});
}
})
.catch((e) => console.warn(e));
};
render() {
return (
<View style={styles.container}>
<FlatList
keyExtractor={(item, index) => index.toString()}
data={this.state.saved}
renderItem={({ item }) => {
return (
<TouchableScale
activeScale={0.9}
tension={50}
friction={7}
useNativeDriver
onPress={() =>
this.props.navigation.navigate("DetailScreen", { data: item })
}
>
<Card item={item} />
</TouchableScale>
);
}}
/>
{this.state.saved.length > 0 && (
<TouchableOpacity onPress={this.removeItem} style={styles.button}>
<Text style={styles.save}>Remove Key</Text>
</TouchableOpacity>
)}
</View>
);
}
}
import { AsyncStorage } from "react-native";
export const SaveItem = async (key, value) => {
try {
await AsyncStorage.setItem(key, value);
console.log("saved");
} catch (e) {
console.log(e);
}
};
export const ReadItem = async (key) => {
try {
var result = await AsyncStorage.getItem(key);
return result;
} catch (e) {
return e;
}
};
export function MultiRead(key, onResponse, onFailure) {
try {
AsyncStorage.multiGet(key).then((values) => {
let responseMap = new Map();
values.map((result, i, data) => {
let key = data[i][0];
let value = data[i][1];
responseMap.set(key, value);
});
onResponse(responseMap);
});
} catch (error) {
onFailure(error);
}
}
export async function DeleteItem(key) {
try {
await AsyncStorage.removeItem(key);
return true;
} catch (exception) {
return false;
}
}