使用钩子将 React Context 与 AsyncStorage 结合使用

时间:2021-04-12 13:53:29

标签: javascript reactjs react-native

  1. 我的目标是使用从上下文创建的自定义钩子来传递和修改存储的值
  2. 最终目标是使用 useFeedContext() 之类的东西来获取或修改上下文值
  3. 我实际得到的是我调用的函数未定义或其他一些问题(我尝试了多种方法)

我尝试将这个视频 basics of react context 与此主题 How to change Context value while using React Hook of useContext 结合起来,但我显然搞错了。

这是我尝试过的:

返回部分 App.js

    <FeedProvider mf={/* what do i put here  */}>
      <Navigation>
        <HomeScreen />
        <ParsedFeed />
        <FavScreen />
      </Navigation>
    </FeedProvider>

主要提供者逻辑

import React, { useState, useEffect, useContext, useCallback } from "react";
import AsyncStorage from "@react-native-async-storage/async-storage";

const FeedContext = React.createContext();

const defaultFeed = [];


const getData = async (keyName) => {
  try {
    const jsonValue = await AsyncStorage.getItem(keyName);
    return jsonValue != null ? JSON.parse(jsonValue) : null;
  } catch (e) {
    console.log(e);
  }
};
const storeData = async (value, keyName) => {
  console.log(value, keyName);
  try {
    const jsonValue = JSON.stringify(value);
    await AsyncStorage.setItem(keyName, jsonValue);
  } catch (e) {
    console.log(e);
  }
};

export const FeedProvider = ({ children, mf }) => {
  const [mainFeed, setMainFeed] = useState(mf || defaultFeed);
  const [feedLoaded, setFeedLoaded] = useState(false);

  let load = async () => {
    let temp = await AsyncStorage.getItem("mainUserFeed");
    temp != null
      ? getData("mainUserFeed").then((loadedFeed) => setMainFeed(loadedFeed))
      : setMainFeed(defaultFeed);
    setFeedLoaded(true);
  };
  useEffect(() => {
    load();
  }, []);

  useCallback(async () => {
    if (!feedLoaded) {
      return await load();
    }
  }, [mainFeed]);

  const setFeed = (obj) => {
    setMainFeed(obj);
    storeData(mainFeed, "mainUserFeed");
  };

  return (
    <FeedContext.Provider value={{ getFeed: mainFeed, setFeed }}>
      {children}
    </FeedContext.Provider>
  );
};

//export const FeedConsumer = FeedContext.Consumer;

export default FeedContext;

自定义钩子

import { useContext } from "react";
import FeedContext from "./feedProviderContext";

export default function useFeedContext() {
  const context = useContext(FeedContext);

  return context;
}

我希望能够在导入后在应用程序的任何位置调用 useFeedContext 钩子,例如:

let myhook = useFeedContext() 

console.log(myhook.getFeed) /// returns the context of the mainFeed from the provider
myhook.setFeed([{test:1},{test:2}]) /// would update the mainFeed from the provider so that mainFeed  is set to the passed array with two objects. 

我希望这一切都是有道理的,我花了更长的时间来承认这一点,因此非常感谢任何帮助。

1 个答案:

答案 0 :(得分:1)

如果您想继续使用您的 useFeedContext 函数,我建议将其移动到您的“提供者逻辑”中,或者我将其称为“FeedContext.tsx”

FeedContext.tsx

const FeedContext = createContext({});
export const useFeedContext = () => {
  return useContext(FeedContext);
}

export const AuthProvider = ({children}) => {
  const [mainFeed, setMainFeed] = useState(mf || defaultFeed);
  ...
  return (
    <FeedContext.Provider value={{mainFeed, setMainFeed}}>
      {children}
    </FeedContext.Provider>
  );
};

YourScreen.tsx

const YourScreen = () => {
  const {mainFeed, setMainFeed} = useFeedContext();

  useEffect(() => {
    // You have to wait until mainFeed is defined, because it's asynchronous.
    if (!mainFeed || !mainFeed.length) {
      return;
    }

    // Do something here
    ...
  }, [mainFeed]);

  ...
  return (
    ...
  );
};

export default YourScreen;