#react-native #react-hooks #use-state #react-state
Вопрос:
Надеюсь, у тебя все отлично получается 🙂
Я работаю над функцией «Любимый экран», где я хочу добавить понравившиеся упражнения на этот экран. Все прошло идеально, моя проблема в том, что экраны не отображаются повторно при нажатии кнопки, а только при повторном рендеринге приложения. Вот пользовательский крючок:
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 для прослушивания изменений в хранилище, даже создал setStorageDB для доступа во всех приложениях, но ничего не сработало.
Ответ №1:
немного сложно следовать вашему коду и точно понимать, что вы пытаетесь сделать, однако экран будет отображаться повторно только в том случае, если переменная состояния будет переназначена. Таким образом, избранное внутри useState должно быть переназначено, чтобы получить повторный отправитель.
Например, toggleFavorite не вызывает setFavorites, поэтому это не приведет к повторному показу экрана, если вы хотите, чтобы экран был повторно показан, вам нужно будет вызвать setFavorites(newFavourites), где newFavorites имеет другую ссылку на текущие избранные.
Я надеюсь, что это поможет, обычно я включал бы больше кода, но, как я уже сказал, немного сложно понять, чего именно вы хотите, не стесняйтесь комментировать, если у вас есть дополнительные вопросы.
Комментарии:
1. Эй, Адам! Извините, что не добавил больше кода, но я беспокоился о том, чтобы загрязнить сообщение слишком большим количеством информации. Проект запутан переменными useContext, пользовательскими связями с событиями AsyncStorage, что немного запутанно, чтобы поместить все здесь. Но ты прав. Благодаря тебе я все понял! Я опубликую решение. Спасибо вам за сочувствие! 🙂
Ответ №2:
Поток, который я намеревался, был:
- Когда пользователю нравится упражнение:
- Объект упражнения обновляется в локальном хранилище и передается на экран Избранное:
Моя проблема заключалась в том, что, когда пользователю не нравилось упражнение, оно не обновляло оба компонента («Счастье» и «Избранное»). Я решил эту проблему с помощью navigation.addListenter и создания локального состояния для избранного экрана (как упоминал Адам).
Вот строка в Избранном:
useEffect(() => {
navigation.addListener("focus", () => setFavorites(updatedFavorites()));
}, []);
Вот линия счастья:
useEffect(() => {
navigation.addListener("focus", () => setKey((prevKey) => prevKey 1));
}, []);
Теперь каждый раз, когда мы вводим эти компоненты, они будут повторно отображаться, если будут внесены изменения 🙂