重构/改进循环,以在“ no-loop-func”之后进行API调用并处理数组

问题描述

尽管在stackoverflow上查找并遵循了许多答案,但我仍然无法重构此代码以遵守ESLint no-loop-func

尽管我努力重构代码,但我仍然收到以下警告:

Compiled with warnings.

Function declared in a loop contains unsafe references to variable(s) 'lastResult','biologyBooks','page'  no-loop-func

这是代码

import React from 'react';
import { apiFullCall } from '../../apiHelper';

const MyComponent = props => {

  const [state,setState] = React.useState({ total: 0,biologyBooksByAuthor: [] });
  let isLoaded = React.useRef(true);

  const token = sessionStorage.getItem('token');
  const authorID = sessionStorage.getItem('author_id');
  
  const getBooks = async() => { // fetch items

    let page = 1;
    let scienceBooks,biologyBooks; 

    // create empty arrays to store book objects for each loop
    let scienceBooks = biologyBooks = [];

    // create a lastResult object to help check if there is a next page
    let lastResult = { next: null };


    do { // the looping - this is what I have Failed to refactor
      try {
        await apiFullCall( // Make API calls over paginated records
          '',token,'get',`books/?author_id=1&page=${page}` 
        ).then(res => {
          if (res) {
            const { status,body } = res;

            if (status === 200 || status === 201) {
              
              lastResult = body; // assign lastResult to pick "next"
    
              body && 
                body.results && 
                  body.results.map(eachBook => { // we map() over the returned "results" array

                      // the author with queried "author_id" writes science books; 
                      // so we add each book (an object) into the science category

                      scienceBooks.push(eachBook);

                      // We then filter the author's biology books (from other science books)

                      biologyBooks = scienceBooks.filter(
                        ({ is_biology }) =>
                          typeof(is_biology) === "boolean" && is_biology === true
                      );

                      return null;
                    }
              );

              // increment the page with 1 on each loop
              page++;
            }
          }
        }).catch(error => console.error('Error while fetching data:',error));

      } catch (err) { console.error(`Oops,something went wrong ${err}`); }

      // keep running until there's no next page
    } while (lastResult.next !== null);

    // update the state
    setState(prevstate => ({
      ...prevstate,total: scienceBooks.length,biologyBooksByAuthor: biologyBooks,}));
  };
  
  React.useEffect(() => { // fetch science books by author (logged in)

    if (isLoaded && authorID) {
      getBooks();
    };
    
    return function cleanup() {...}; // clean up API call,on unmount

  },[isLoaded,authorID]);

  return (
     // render the JSX code
  );

}

请注意,我实际上是在“ do-while”之外声明了所述变量lastResultbiologyBookspage

任何帮助或线索将不胜感激。

解决方法

警告所指的功能是.then回调,如果您使用的是async/await,请尝试通过将结果分配给变量来删除.then部分并删除不必要的.map,您可以使用传播运算符或.concat合并先前的结果。

import React from 'react';
import { apiFullCall } from '../../apiHelper';

const MyComponent = props => {
  const [state,setState] = React.useState({
    total: 0,scienceBooksByAuthor: [],});
  const isLoaded = React.useRef(true);

  const token = sessionStorage.getItem('token');
  const authorID = sessionStorage.getItem('author_id');

  const getBooks = async () => {
    // fetch items

    let page = 1;
    let scienceBooks = [];

    // create a lastResult object to help check if there is a next page
    let lastResult = { next: null };

    do {
      // the looping - this is what I have failed to refactor
      try {
        const res = await apiFullCall(
          // Make API calls over paginated records
          '',token,'get',`books/?author_id=1&page=${page}`,);
        if (res) {
          const { status,body } = res;

          if (status === 200 || status === 201) {
            lastResult = body; // assign lastResult to pick "next"

            // concatenate new results
            scienceBooks = [
              ...scienceBooks,...((lastResult && lastResult.results) || []),];

            // increment the page with 1 on each loop
            page += 1;
          }
        }
      } catch (err) {
        console.error(`Oops,something went wrong ${err}`);
      }

      // keep running until there's no next page
    } while (lastResult.next !== null);
    
    const biologyBooks = scienceBooks.filter(
      ({ is_biology }) =>
        typeof is_biology === 'boolean' && is_biology === true,);

    // update the state
    setState(prevState => ({
      ...prevState,total: scienceBooks.length,scienceBooksByAuthor: scienceBooks,}));
  };

  React.useEffect(() => {
    // fetch science books by author (logged in)

    if (isLoaded && authorID) {
      getBooks();
    }

    return function cleanup() {...}; // clean up API call,on unmount
  },[isLoaded,authorID]);

  return (
    // render the JSX code
  );
};