我有一个主屏幕,在那里你可以看到以卡片形式显示的多个项目。你可以通过按下它来访问项目以查看其详细信息。在详细信息屏幕上,我添加了一个书签选项,可以使用异步存储保存项目。你也可以在另一个名为savedItems屏幕的屏幕上检查保存的项目。
问题是:
-
当我为一个项目添加书签时,它会被正确保存,我可以转到savedItems屏幕并在那里找到它,但有时我必须重新加载应用程序才能使该项目出现在savedItemss屏幕上,这是为什么?
-
如果我预订了多个项目,它们都会被保存(在console.log上(,但由于某种原因只有最后一个出现,我永远不会在SavedItems屏幕上显示超过一个项目
Bellow是用于预订标记的代码片段(在其详细信息屏幕上保存了一个项目(
Details.js
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>
)
SaveScreen.js
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>
);
}
}
用于使用异步存储保存数据的代码
Dbhelper.js
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;
}
}
如果我预订了多个项目,它们都会被保存(在console.log上(,但由于某种原因只显示最后一个项目,我永远不会在SavedItems屏幕上显示超过一个项目
我认为问题是当你保存新项目时,你会删除旧项目。当您装载DetailScreen
时,您必须读取旧项目。或者,您可以读取onSave方法中的项。这更安全。这取决于您的应用程序架构
const DetailScreen = (props) => {
const [items, setItems] = useState(props.route.params);
const onSave = (item) => {
let saved = [];
ReadItem("saved")
.then((res) => {
if (res) {
saved = JSON.parse(res);
}
const newItems = [...saved, item];
const items = JSON.stringify(newItems);
SaveItem("saved", items).then((res) => {
console.log("saved", res);
});
})
.catch((e) => console.warn(e));
};
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>
)
当我为一个项目添加书签时,它会被正确保存,我可以转到savedItems屏幕并在那里找到它,但有时我必须重新加载应用程序才能使该项目出现在savedItemss屏幕上,这是为什么?
我只知道为什么会发生这种情况。在某些情况下,您不会卸载SaveScreen
。当您返回到SaveScreen
组件时,不会调用DidMount。只需尝试将console.log添加到componentDidMount中,当您再现此行为时,如果console.log丢失,则意味着您的SaveScreen
没有卸载
要处理所有情况,您可以尝试这样做:
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 = () => {
this.readItems();
this.unsubscribe = navigation.addListener('focus', this.readItems);
};
componentWillUnmount() {
this.unsubscribe();
}
readItems = () => {
ReadItem("saved")
.then((res) => {
if (res) {
const saved = JSON.parse(res);
this.setState({
saved: saved,
});
}
})
.catch((e) => console.warn(e));
}
render() { ... }
}