【问题标题】:singleton object in react native反应原生的单例对象
【发布时间】:2017-11-26 21:30:33
【问题描述】:

我是 react native 的新手。我想将多个小字符串存储到常见的单例对象类中,并希望从所有组件的单例对象中访问它。任何人都可以帮我实现反应原生的单例对象。

组件 1 -- 登录按钮 -- >> 成功 --> 需要将用户 ID 存储到单例对象中。

组件 2 --> 从单例对象中获取存储的用户 ID。我该如何实现它。

【问题讨论】:

    标签: react-native


    【解决方案1】:

    TS 类示例:

    export class SingletonClass
    {
        private static _instance: SingletonClass;
    
        public anyMetod(_value:any):any
        {
             return _value;
        }
        public static getInstance(): SingletonClass
        {
            if (SingletonClass._instance == null)
            {
                SingletonClass._instance = new SingletonClass();
            }
            return this._instance;
        }
        constructor()
        {
            if(SingletonClass._instance)
            {
                throw new Error("Error: Instantiation failed: Use SingletonClass.getInstance() instead of new.");
            }
        }
    }
    

    用途:

    SingletonClass.getInstance().anyMetod(1);
    

    【讨论】:

      【解决方案2】:

      我可能为时已晚,但我不妨根据 Yeshan Jay 的回答分享我自己的实现。

      export default class Data {
      
          static instance = null;
          _state = {};
          static get inst() {
              if (Data.instance == null) {
                  Data.instance = new Data();
              }
              return this.instance;
          }
          static get state() { 
              return Data.inst._state; 
          }
          static set state(state) { 
              Data.inst._state = state; 
          }
          static setState(state) { 
              Data.inst._state = {...Data.inst._state, ...state} 
          }
      }
      

      这就是你如何使用它。它几乎模仿了 React 组件的状态行为,因此您应该感到宾至如归,几乎无需调整,无需经常修改 Singleton 以不时添加新属性。

      import Data from './Data'
      
      // change the whole singleton data
      Data.state = { userId: "11231244", accessToken: "fa7sd87a8sdf7as" } 
      
      // change only a property
      Data.setState ({ userId: "1231234" }) 
      
      // get a single property directly
      console.log("User Id: ", Data.state.userId) 
      
      // get a single property or more via object deconstruction
      const { userId, property } = Data.state
      console.log("User Id: ", userId) 
      

      【讨论】:

        【解决方案3】:

        这是一个简单的方法......

        export default class CommonDataManager {
        
            static myInstance = null;
        
            _userID = "";
        
        
            /**
             * @returns {CommonDataManager}
             */
            static getInstance() {
                if (CommonDataManager.myInstance == null) {
                    CommonDataManager.myInstance = new CommonDataManager();
                }
        
                return this.myInstance;
            }
        
            getUserID() {
                return this._userID;
            }
        
            setUserID(id) {
                this._userID = id;
            }
        }
        

        这里是如何使用它...

        import CommonDataManager from './CommonDataManager';
        
        
        // When storing data.
        let commonData = CommonDataManager.getInstance();
        commonData.setUserID("User1");
        
        
        // When retrieving stored data.
        let commonData = CommonDataManager.getInstance();
        let userId = commonData.getUserID();
        console.log(userId);
        

        希望这对你有用:)

        【讨论】:

        • 假设如果我退出应用程序并重新打开应用程序需要从单例对象获取存储的用户 ID,我该怎么做?
        • 在这种情况下,您必须实现在 setter 方法中持久化数据。你可以试试AsyncStorage。我上面所做的是内存中的临时存储。你也可以看看这个..react-native-storage
        • 我无法使用上面的代码创建。它在线崩溃 let commonData = CommonDataManager.getInstance();
        • 然后把let关键字改成var看看..我认为这是一个旧版本的js引擎。
        • 有一个错字。应该是return this.myInstance;
        【解决方案4】:

        我建议创建一个使用AsyncStorage 存储数据的静态类。 您在评论中提到您已经在使用AsyncStorage,但不喜欢在您的应用程序中传播此功能。 (即到处都是try-catches,每个组件都需要检查密钥是否可用等)如果这个功能在一个类中,它会清理你的代码很多。

        这种方法的另一个好处是您可以很容易地换出实现,例如,您可以选择使用内存中的对象或AsyncStorage 或其他任何东西,您只需要更改这个文件

        注意:AsyncStorage不是存储敏感信息的安全方式。请参阅this question,了解有关AsyncStorage 和替代方案的安全性的更多信息。

        也就是说,这就是我想象的全局数据持有者类的样子:

        export default class dataManager {
          static storeKeyValue(key, value) {
            // your choice of implementation:
            // check if key is used
            // wrap in try-catch
            // etc.
          }
        
          static getValueForKey(key) {
            // get the value out for the given key
          }
        
          // etc...
        }
        

        然后要在您的应用中的任何地方使用这个类,只需像这样在需要的地方导入:

        import dataManager from 'path/to/dataManager.js';
        
        // store value
        dataManager.storeKeyValue('myKey', 'myValue');
        
        // get value
        const storedValue = dataManager.getValueForKey('myKey');
        

        编辑:在大多数情况下,使用 FluxRedux 或类似技术可能是首选/建议的方法,但如果您觉得单例模式最适合您的应用程序那么这是一个很好的方法。 You Might Not Need Redux

        【讨论】:

        • 在我看来 Redux / Flux 是一个糟糕的系统。我看了看,我只是不明白你为什么会使用它,而不是仅仅将不同模型的状态封装在一个单例中。你只需要用 Redux 编写这么多不必要的代码,而且你必须有用于操作的 switch 语句等。在我看来,它不必要地过于复杂,并且与单例模式为你做的事情基本相同。
        【解决方案5】:

        有一个解决方法,在编译阶段对原生打包器require所有模块进行反应以生成一个包,并在首先要求它为模块生成一个内部id之后,从那时起在整个运行时内存,因此,如果我们从文件中导出类的实例,则每次导入该文件时都会引用该对象。

        TLDR;

        解决方案一:

        class abc {
        
        }
        
        
        module.exports = new abc()
        

        解决方案二:我假设您想要获取静态且不会更改的字符串,因此您可以将它们声明为静态并使用类名直接访问它们

        仅供参考:这也适用于 webpack。

        【讨论】:

        • 例如,我有两个组件。组件 1 -- 登录按钮 -- >> 成功 --> 需要将用户 ID 存储到单例对象中。组件 2 --> 从单例对象中获取存储的用户 ID。我该如何实现它。假设如果我退出应用程序并重新打开应用程序需要从单例对象获取存储的用户 ID。
        • 为此,我建议您使用facebook.github.io/react-native/releases/0.45/docs/… AsyncStorage,这为您提供了类似于浏览器中的localStorage 的持久存储。它将值存储在沙箱中,您可以在退出并重新打开后访问它。
        • 目前我只使用 AsyncStorage,这是冗长的代码我有 n 个组件类,每个类都需要检查可用的 AsyncStorage 密钥并尝试捕获处理是任何其他替代解决方案吗?
        • 我提出的上述解决方案应该可以工作,我不确定退出应用程序并重新启动它的情况,它可能会工作并且是一个更简洁的解决方案,如果你尝试让我也知道。
        • 你想过实现 redux 吗?
        猜你喜欢
        • 2020-08-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-03-14
        相关资源
        最近更新 更多