【问题标题】:React-Native (expo) Retrieve an Initial Theme (or any initializing value)React-Native (expo) 检索初始主题(或任何初始化值)
【发布时间】:2021-06-10 16:36:27
【问题描述】:

我想为我的(expo 增强版)react-native 应用程序引入一个简单的可配置主题,最初的重点是背景颜色。我在实现动态方面取得了一些成功,例如用户可以在应用程序中选择主题/背景颜色,该颜色会影响所有屏幕。我使用了一种相当典型的技术,其中 App.js 将其 (V5) NavigationContainer 及其主题包装在 Context 提供程序中,例如

return (
  <SomeProvider>
       <NavigationContainer theme={AppDefaultTheme} ref={navigationRef}>
        ... stuff including navigators
       <NavigationContainer>
  </SomeProvider>
)

在组件方面,我们可以使用 useTheme 挂钩检索主题(最初是默认主题),然后更改背景或其他任何内容,并(暂时)将变异的主题持久保存在 Provider 的 reducer 中。 reducer 还可以将变异的主题持久化到 AsyncStorage 之类的东西中,以便下次应用程序启动。

问题出在应用重启。

似乎没有办法及时从 App.js 中的冷存储(AsyncStorage 或其他)中检索当前主题以将其提供给 NavigationContainer

(记住这一点) &lt;NavigationContainer theme={AppDefaultTheme} ref={navigationRef}&gt;

许多帖子指出在 RN/expo 中 没有 beforeRender 钩子或功能。当我们在 useEffect 挂钩中拉回 AppDefaultTheme 时,App.js NavigationContainer 早已离开了站点。

我猜想检索初始状态是不可能的,除非可能使用像 Redux 这样的外部状态管理器。 Redux 人是怎么解决这个问题的?我对“nonReduxLight”非常满意,例如redux 模式使用上述 Provider 包装器,颜色主题功能还不足以让我潜入那个深游泳池,但它已经接近了。

Redux 会做我想做的事吗?有没有更简单的方法?

【问题讨论】:

    标签: react-native redux expo asyncstorage use-context


    【解决方案1】:

    很高兴有兴趣。现在我会回答我自己的问题,因为研究成果丰硕。

    Expo 提供 AppLoading 包,该包似乎“保持”初始启动屏幕,同时执行其他通常异步操作。

    这会启用以下模式:

    1. App.js(或您的初始组件)根据应用程序状态在渲染/返回方法中调用 AppLoading。状态不需要绑定到上下文,因此在创建上下文之前它可以在 App.js 中正常工作。
    2. AppLoading 阻止组件在初始屏幕上渲染,并调用包含渲染前要完成的工作的函数。
    3. 在调用的函数中执行您需要执行的任何操作来初始化应用程序。在此特定示例中,我们希望在 App.js 访问应用程序并将其包装在上下文中之前,从冷存储中检索可修改的主题。被调用函数中的水合操作通常是异步的,但我认为不需要。
    4. 当承诺兑现时,例如您已经为从网络或冷存储中获取的任何内容添加了水分,翻转了使初始屏幕处于悬念状态的状态,这允许进一步渲染,并消耗您添加的结果。在这种特殊情况下,使用检索到的主题来初始化导航器

    我在 Expo 40 中使用它,这种模式效果很好。从架构上讲,它是一个很好的模式......它在生命周期中插入了一个“在渲染任何东西之前”,它不如没有的“在渲染这个组件之前”事件那么好,但对于执行前水合的目的,它是完美的。

    它完全不依赖于上下文,所以它可以在调用上下文来包装应用程序之前在 App.js 中使用。

    几条笔记,然后是一些例子:

    1. 我只在 Expo 中测试过,但组件说明表明它可以 通过导入初始依赖项或在 vanilla react-native 中使用 两个
    2. package documentation and example 很棒,但指的是基于类的组件。如果您像我一样喜欢功能组件,这里有一个很棒的functional component example
    3. AppLoading 组件似乎是 Expo SplashScreen 组件的便捷包装器,它添加了一些我现在不需要的额外功能。你可能会。
    4. 令人难以置信的酷...可用于多个组件。例如,您可能有一个加载主题的组件,根据我们的主要用例可能在 App.js 中。根据本文的大部分内容,App.js 工作不需要访问 Context,实际上必须在创建上下文之前进行。
    5. 但您可能有另一个组件需要从 Web 或冷存储加载一些首选项,并且它确实需要访问 Context。没问题。将 AppLoading 的另一个实现放在第二个组件中并水合。

    不要混淆...... 两个 AppLoading 调用都在等待同一组事件以释放初始屏幕,因此这不是解决“渲染前禁止”一般问题的方法.但它看起来确实是解决“渲染前任何东西问题的解决方案。

    最后一个......似乎有很多使用 Redux 进行水合的解决方案来解决这个问题——而且它们可能都很好。然而,这种情况并没有上升到重写应用程序的程度,该应用程序大量且愉快地使用 Context hooks 而不是 Redux。如果我曾经使用 Redux 学习和重写,我可能会在那里补充水分。

    好的,废话不多说。这是模式的基础知识。 getColorTheme 是一种自定义方法,可以执行任何所需的操作来获取冷存储数据。

    在 App.js 或任何首先加载的内容中:

    import React, { useState } from 'react';
    import AppLoading from 'expo-app-loading';
    ... whatever else you need
        
    function App() {
    
      // This bit of component state controls whether apploading is finished or not
      const [isReady, setReady] = useState(false);  
      // This piece of component state holds the hydrated theme to pass to navigation
      const [colorTheme, setColorTheme] = useState({});
      ...
      // Invoked while the splash screen is showed.  Initialize resources here
      const _cacheResourcesAsync = async () => {
        const storedColorTheme = await getColorTheme(); // an app specific method to fetch theme from cold storage
        setColorTheme(storedColorTheme)  // now stash the theme in state for retrieval in render
        return;
      }
    
    and eventually render and invoke our method using AppLoading:
            
      return (
        // Carry out initializing actions, then release the splash screen
        isReady === false ? (<AppLoading
           startAsync={_cacheResourcesAsync}
           onFinish={() => setReady(true)}
           onError={console.warn}
          />) :
            
          <MyContextProvider>
          <NavigationContainer theme={colorTheme} ...>
    

    【讨论】:

      猜你喜欢
      • 2022-11-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-12-11
      • 2018-11-21
      • 2018-12-05
      • 2016-05-08
      相关资源
      最近更新 更多