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

Posted

技术标签:

【中文标题】使用钩子将 React Context 与 AsyncStorage 结合使用【英文标题】:Using React Context with AsyncStorage using hooks 【发布时间】:2021-07-07 14:39:51 【问题描述】:
    我的目标是使用从 Context 创建的自定义挂钩来传递和修改存储的值 最终目标是使用 useFeedContext() 之类的东西来获取或修改上下文值 我实际得到的是我调用的函数未定义或其他问题(我尝试了多种方法)

我尝试关注此视频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】:

如果您想继续使用您的 useFeedContext 函数,我建议将其移至您的“Provider Logic”,或者我将其称为“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;

【讨论】:

非常感谢!我认为 useEffect 和 useCallback 的循环足以加载 mainFeed 并因此在其他屏幕中使用。 :D

以上是关于使用钩子将 React Context 与 AsyncStorage 结合使用的主要内容,如果未能解决你的问题,请参考以下文章

使用带有 useReducer() 钩子的 React Context API 有啥优点和缺点?

React context API-我如何从 useEffect 钩子中分派一个动作?

React - 如何获取上下文中钩子的值

React Context Hook vs 将数据直接引入组件

如何将 React useRef 钩子与打字稿一起使用?

是否可以将 react-datepicker 与反应钩子形式一起使用?