如何在 React Native 中创建全局状态?
How to create a global state in React Native?
希望你做得很好:)
我正在使用收藏屏幕功能,我想将喜欢的练习添加到该屏幕。一切都很完美,我的问题是屏幕 不会在单击按钮时重新呈现 ,只有当应用程序 re-render 时才会重新呈现。这是自定义挂钩:
const useStorage = (name, id, pratice, navigation) => {
const [favorites, setFavorites] = useState();
const { storageDB } = useContext(StorageContext);
//Favorites Actions
const getFavorites = () => {
const checkFavorites = storageDB.map((store) =>
store.exercises.filter((exArray) => exArray.favorite)
);
const favoritesResult = checkFavorites.filter((ex) => ex.length !== 0);
if (favoritesResult.length !== 0) return setFavorites(favoritesResult);
return null;
};
const toggleFavorite = () => {
//Find exercise
const exerciseIndex = storageDB[topicIndex()].exercises.findIndex(
(ex) => ex.id === id
);
//Topic > Exercise
const exercise = storageDB[topicIndex()].exercises[exerciseIndex];
//Toogle favorite
exercise.favorite = !exercise.favorite;
//Store in AsyncStorage
storage.storeData(storageDB);
};
useEffect(() => {
getFavorites();
}, []);
return {
storageDB,
getFavorites,
toggleFavorite,
favorites
};
};
export default useStorage;
钩子参数是为了在存储中进行正确的练习,并在 getFavorites() 中调用一次。
这是收藏夹屏幕:
const FavoritesScreen = () => {
const { favorites } = useStorage();
const Favorites = () => {
if (favorites)
return favorites.map((exArray) =>
exArray.map((ex) => (
<Card
key={ex.id}
exercise={ex}
topicName={ex.topicName}
onPress={() =>
navigation.navigate("ExerciseDetails", {
exercise,
name: ex.topicName
})
}
/>
))
);
return <NotFound text="No favorite exercises" noImage />;
};
return (
<Screen>
<Image source={require("../assets/favorites.png")} style={styles.image} />
<Title style={styles.title}>Favorites</Title>
<View style={styles.searchContainer}>
<SearchInput />
</View>
<Container scrollView>
<Favorites />
</Container>
</Screen>
);
};
我尝试了很多东西,使用 useEffect 来监听 storageDB 中的变化,甚至创建了一个 setStorageDB 以在所有应用程序中访问,但没有任何效果。
遵循您的代码并准确理解您正在尝试做什么有点困难,但是如果重新分配状态变量,屏幕只会重新呈现。因此必须重新分配 useState 中的收藏夹才能重新呈现。
例如,toggleFavorite 不会调用 setFavorites,因此它不会导致屏幕重新呈现,如果您希望屏幕重新呈现,则需要调用 setFavorites(newFavourites),其中 newFavorites 对当前收藏夹有不同的引用。
我希望这对您有所帮助,通常我会包含更多代码,但正如我所说,要准确计算出您想要的内容有点棘手,如果您有其他问题,请随时发表评论。
我想要的流程是:
- 当用户喜欢这个练习时:
- 练习 object 在本地存储中更新 并传递到收藏夹屏幕:
我的问题是当用户不喜欢练习时,它没有更新两个组件(幸福和收藏夹)。我已经使用 navigation.addListenter 解决了它并为 Favorite Screen 创建了一个本地状态(正如 Adam 所提到的)。
这是收藏夹中的行:
useEffect(() => {
navigation.addListener("focus", () => setFavorites(updatedFavorites()));
}, []);
Happiness 中的一行:
useEffect(() => {
navigation.addListener("focus", () => setKey((prevKey) => prevKey + 1));
}, []);
现在每次我们输入这些组件时,如果有变化,它们将 re-render:)
希望你做得很好:)
我正在使用收藏屏幕功能,我想将喜欢的练习添加到该屏幕。一切都很完美,我的问题是屏幕 不会在单击按钮时重新呈现 ,只有当应用程序 re-render 时才会重新呈现。这是自定义挂钩:
const useStorage = (name, id, pratice, navigation) => {
const [favorites, setFavorites] = useState();
const { storageDB } = useContext(StorageContext);
//Favorites Actions
const getFavorites = () => {
const checkFavorites = storageDB.map((store) =>
store.exercises.filter((exArray) => exArray.favorite)
);
const favoritesResult = checkFavorites.filter((ex) => ex.length !== 0);
if (favoritesResult.length !== 0) return setFavorites(favoritesResult);
return null;
};
const toggleFavorite = () => {
//Find exercise
const exerciseIndex = storageDB[topicIndex()].exercises.findIndex(
(ex) => ex.id === id
);
//Topic > Exercise
const exercise = storageDB[topicIndex()].exercises[exerciseIndex];
//Toogle favorite
exercise.favorite = !exercise.favorite;
//Store in AsyncStorage
storage.storeData(storageDB);
};
useEffect(() => {
getFavorites();
}, []);
return {
storageDB,
getFavorites,
toggleFavorite,
favorites
};
};
export default useStorage;
钩子参数是为了在存储中进行正确的练习,并在 getFavorites() 中调用一次。
这是收藏夹屏幕:
const FavoritesScreen = () => {
const { favorites } = useStorage();
const Favorites = () => {
if (favorites)
return favorites.map((exArray) =>
exArray.map((ex) => (
<Card
key={ex.id}
exercise={ex}
topicName={ex.topicName}
onPress={() =>
navigation.navigate("ExerciseDetails", {
exercise,
name: ex.topicName
})
}
/>
))
);
return <NotFound text="No favorite exercises" noImage />;
};
return (
<Screen>
<Image source={require("../assets/favorites.png")} style={styles.image} />
<Title style={styles.title}>Favorites</Title>
<View style={styles.searchContainer}>
<SearchInput />
</View>
<Container scrollView>
<Favorites />
</Container>
</Screen>
);
};
我尝试了很多东西,使用 useEffect 来监听 storageDB 中的变化,甚至创建了一个 setStorageDB 以在所有应用程序中访问,但没有任何效果。
遵循您的代码并准确理解您正在尝试做什么有点困难,但是如果重新分配状态变量,屏幕只会重新呈现。因此必须重新分配 useState 中的收藏夹才能重新呈现。
例如,toggleFavorite 不会调用 setFavorites,因此它不会导致屏幕重新呈现,如果您希望屏幕重新呈现,则需要调用 setFavorites(newFavourites),其中 newFavorites 对当前收藏夹有不同的引用。
我希望这对您有所帮助,通常我会包含更多代码,但正如我所说,要准确计算出您想要的内容有点棘手,如果您有其他问题,请随时发表评论。
我想要的流程是:
- 当用户喜欢这个练习时:
- 练习 object 在本地存储中更新 并传递到收藏夹屏幕:
我的问题是当用户不喜欢练习时,它没有更新两个组件(幸福和收藏夹)。我已经使用 navigation.addListenter 解决了它并为 Favorite Screen 创建了一个本地状态(正如 Adam 所提到的)。
这是收藏夹中的行:
useEffect(() => {
navigation.addListener("focus", () => setFavorites(updatedFavorites()));
}, []);
Happiness 中的一行:
useEffect(() => {
navigation.addListener("focus", () => setKey((prevKey) => prevKey + 1));
}, []);
现在每次我们输入这些组件时,如果有变化,它们将 re-render:)