首页 > 解决方案 > 从复杂的反应组件中拆分逻辑

问题描述

介绍

我真的不知道从大屏幕上拆分逻辑(获取或其他类型的逻辑)。我的意思是,在一个组件中拥有比 JSX 标签更多的逻辑似乎真的很不专业,而且我确信我不是世界上唯一遇到这种问题的开发人员,所以我决定在这里提问,以获得一个好的答案.

在我的用例中,我使用 Firebase CLI 从我的数据库中获取数据

/users (collection)
     userId (document)
         -name
         -avatar
         -age

/bosses (collection)
    userId (document)
         -other info

/cellebrety (collection)
    userId (document)
         -other info

/filmmakers (collection)
    userId (document)
         -other info

/books (collection)
    userId (document)
       userBooks (collection)
          bookId (document)
              -book info

...

以及用于身份验证、将图像存储到我的存储等。

因此,我决定创建一个“Firebase”类,如下所示:

export default function Firebase() {
  if (!firebase.apps.length) {
    // Initialize App
    firebase.initializeApp(Constants.manifest.web.config.firebase);

    // Initialize firebase services
    this.auth = firebase.auth();
    this.firestore = firebase.firestore();
    this.functions = firebase.functions();
    this.storage = firebase.storage();
  }
}

Firebase.prototype.enableAuthPersistence = function () {
  ...
};

Firebase.prototype.signInWithEmailAndPassword = function (email, password) {
  ...
};

Firebase.prototype.signInWithUsernameAndPassword = function (username, password) { 
  ...
};

Firebase.prototype.uploadImageToStorage = async function (
  imageUri,
  storageFolder
) {
  ...
};

Firebase.prototype.getCurrentUser = function () {
  ...
};

...

问题

为了避免将我的所有数据库查询实现为此类的函数,以防止该类成为“上帝”类,我决定将所有查询逻辑放在我呈现内容的屏幕中。但是,一切都变得非常重复,就像在我的应用程序中一样,当它安装、刷新等时,我必须按照类似的语法和相同的模式查询每个屏幕上的内容:

...

const getMoreFilmmakers = () => {
   // Do nothing if currently fetching
   if (isFetching.current) return;

   // Start mutual exclusion
   isFetching.current = true;

   // Perform query
   const query = firebase.firestore.collection("filmmakers").where(...);
   const snapshot = await query.limit(10).get();
   ...


   // Prepare (some kind of parsing) the fetched data
   const filmmakers = prepareFilmmakers(retrievedData);

   // Update states
   setFilmakers(filmmakers)
   setIsLoading(false);
   
   // Stop mutual exclusion
   isFetching.current = false;
}

const prepareFilmmakers = (data) => {
    // Preparing data to be rendered...
}

useEffect(() => {
    getMoreFilmmakers();
}, []);

...

在每个屏幕上都有所有这些东西对我来说似乎是重复的,因为在大多数情况下,唯一改变的是执行查询的集合。

例如,在其他屏幕中,程序员可以这样做:

...

const getMoreBooks = (userId) => {
   // Do nothing if currently fetching
   if (isFetching.current) return;

   // Start mutual exclusion
   isFetching.current = true;

   // Perform query (get the books of a user ordered by cost)
   const query = firebase.firestore.collection("books").doc(userId).collection("userBooks").orderBy("price");
   const snapshot = await query.limit(10).get();
   ...

   // Prepare (some kind of parsing) the fetched data
   const books = prepareBooks(retrievedData);

   // Update states
   setBooks(books)
   setIsLoading(false);
   
   // Stop mutual exclusion
   isFetching.current = false;
}

const prepareBooks = (data) => {
    // Preparing data to be rendered...
}

useEffect(() => {
    getMoreBooks();
}, []);

...

此时,如您所见,代码变得重复,我们只是在所有屏幕上获取、准备(解析)和渲染、复制代码行,仅用于更改集合或查询。

另外,如果在不久的将来我决定在一个屏幕上呈现多个水平列表(执行不同类型的查询)呢?

- list for users
- list for bosses
- list for cellebrity
- list for filmmakers
...

在这种情况下,我将真正拥有一个巨大的屏幕,它可以完美地达到 750 行代码,而且大部分都非常相似......

我曾考虑将所有逻辑移至子组件……但代码仍会重复,因为它只会减少屏幕的行数,将它们移至子组件。

有没有一种简单的方法来处理这个问题并有一种通用的方法来执行查询?任何提示或建议?将逻辑移动到“逻辑”HOC 或挂钩是否正确?谢谢你。

标签: javascriptreactjsfirebasereact-nativerefactoring

解决方案


推荐阅读