React Native - 观察 AsyncStorage 值的变化?

7

有没有一种方法可以订阅 AsyncStorage 值的更改?我在应用程序中的一个地方保存了一个设置,它保存在 AsyncStorage 中,并影响其他所有屏幕。我需要观察这个值,以便更新所有屏幕。我尝试了 getValue 方法,但它似乎只能最初获取值,并且在更改时不会更新。

3个回答

4
我在我的应用程序中通过构建一个与AsyncStorage同步的React Context来解决了这个问题。
在你的情况下,你可以有一个名为“appSettings”的项。这将是一个字符串化的JSON对象,保存了你的所有应用程序设置。
const AppSettingsContext = React.createContext({})

const AppSettingsContextProvider = ({children}) => {
  const [appSettingsInitialized, setAppSettingsInitialized] = useState(false)
  const [appSettings, setAppSettings] = useState({}) // could use some default values instead of empty object

  // On mount, get the current value of `appSettings` in AsyncStorage
  useEffect(() => {
    AsyncStorage
      .getItem('appSettings')
      .then(data => {
        // If data is returned, the storage item existed already and we set the appSettings state to that.
        if (data) {
          setAppSettings(JSON.parse(data))
        }
        // If data is null, the appSettings keeps the default value (in this case an empty object)/

        // We set appSettingsInitialized to true to signal that we have successfully retrieved the initial values.
        setAppSettingsInitialized(true)
      })
  }, [])

  // setSettings sets the local state and AsyncStorage
  const setSettings = (key, value) => {
    const mergedSettings = {
      ...appSettings,
      [key]: value
    }
    // First, merge the current state with the new value
    setAppSettings(mergedSettings)

    // Then update the AsyncStorage item
    AsyncStorage.setItem('appSettings', JSON.stringify(mergedSettings))
  }

  return (
    <AppSettingsContext.Provider value={{
      appSettings,
      appSettingsInitialized,
      setSettings,
    }}>
      {children}
    </AppSettingsContext.Provider>
  )
}

(请注意这是一个相当基本的版本,没有错误处理)

然后将您的应用程序包装在AppSettingsContextProvider中

const App = () => (
  <AppSettingsContextProvider>
    {/* Other components */}
  </AppSettingsContextProvider>
)

然后从任何子组件中消费上下文:

const SomeChildComponent = () => {
  const { appSettingsInitialized, appSettings } = useContext(AppSettingsContext)

  // For example: wait until initial appSettings have been retrieved AsyncStorage,
  // then use some value that you expect to be present in your business logic.
  // In this case, setAppTheme would set the them color for the whole app, using a
  // `theme` setting saved by the user.
  useEffect(() => {
    if (appSettingsInitialized) {
      setAppTheme(appSettings.theme)
    }
  }, [appSettingsInitialized])

  // Update settings like this for example
  const updateThemeSetting = (newThemeValue) => {
    setSettings('theme', newThemeValue) // eg 'dark', 'light', etc
  }
}

0

当然,如果你使用react-native-easy-app帮助你使用AsyncStorage,你可以通过react-native-easy-app获得两个好处,

第一:你可以同步快速地访问AsyncStorage,并且支持直接访问字符串、布尔值、对象、数组等数据。代码片段

第二:当你修改任何AsyncStorage数据时,会有一个回调函数告诉你相应的数据变化。代码片段

详情请参考示例项目

你可以按以下方式使用它:

  import { XStorage } from 'react-native-easy-app';
  import { AsyncStorage } from 'react-native';
  // or import AsyncStorage from '@react-native-community/async-storage';

   export const RNStorage = {
       token: undefined, 
       isShow: undefined, 
       userInfo: undefined
   };

  const initCallback = () => {

       // From now on, you can write or read the variables in RNStorage synchronously

       // equal to [console.log(await AsyncStorage.getItem('isShow'))]
       console.log(RNStorage.isShow); 

       // equal to [ await AsyncStorage.setItem('token',TOKEN1343DN23IDD3PJ2DBF3==') ]
       RNStorage.token = 'TOKEN1343DN23IDD3PJ2DBF3=='; 

       // equal to [ await AsyncStorage.setItem('userInfo',JSON.stringify({ name:'rufeng', age:30})) ]
       RNStorage.userInfo = {name: 'rufeng', age: 30}; 
  };

const dataSetChangedCallback = (data) => {

    data.map(([keyStr, value]) => {
        let [, key] = keyStr.split('#');
        console.log('data has changed:', key, '<###>', value);
    })
};

XStorage.initStorage(RNStorage, AsyncStorage, initCallback, dataSetChangedCallback);

-1

您可以在 useEffect 中使用 AsyncStorage.getItem() 来监视组件挂载后的值。

    useEffect(() => {
    (async () => {
        console.log(await AsyncStorage.getItem('YOUR_ITEM_KEY'));
    })();
}, []);

使用此语法,您可以记录具有键“YOUR_ITEM_KEY”的项目。

如果您正在使用类组件,则可以像这样执行:

show = async () => {
       console.log(await AsyncStorage.getItem('YOUR_ITEM_KEY'));
}

componentDidMount(){
       this.show();
}

我收到错误信息:`无效的钩子调用。钩子只能在函数组件的主体内部调用。这可能是以下原因之一:
  1. React和渲染器(如React DOM)的版本不匹配
  2. 违反了Hooks规则
  3. 在同一个应用程序中可能有多个React副本`
- Simon Moshenko

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接