如何在 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 对当前收藏夹有不同的引用。

我希望这对您有所帮助,通常我会包含更多代码,但正如我所说,要准确计算出您想要的内容有点棘手,如果您有其他问题,请随时发表评论。

我想要的流程是:

  1. 当用户喜欢这个练习时:

  1. 练习 object 在本地存储中更新 并传递到收藏夹屏幕:

我的问题是当用户不喜欢练习时,它没有更新两个组件(幸福和收藏夹)。我已经使用 navigation.addListenter 解决了它并为 Favorite Screen 创建了一个本地状态(正如 Adam 所提到的)。

这是收藏夹中的行:

 useEffect(() => {
    navigation.addListener("focus", () => setFavorites(updatedFavorites()));
  }, []);

Happiness 中的一行:

useEffect(() => {
    navigation.addListener("focus", () => setKey((prevKey) => prevKey + 1));
  }, []);

现在每次我们输入这些组件时,如果有变化,它们将 re-render:)