бесконечный цикл происходит внутри react-native

Вопрос или проблема

Ниже приведен мой код в небольшом проекте react-native. Здесь строка “setcollectionReport(coll);” вызывает бесконечный цикл “console.log(params);”. Если не использовать setcollectionreport(coll), бесконечный цикл не происходит. Но этот процесс неизбежен.

Попробовал исправить это, но не знаю, что делать. Может кто-нибудь помочь?

function Report({navigation,route}){
  
  const [pairedDevices, setPairedDevices] = useState([]);
  const [foundDs, setFoundDs] = useState([]);
  const [bleOpend, setBleOpend] = useState(false);
  const [loading, setLoading] = useState(true);
  const [name, setName] = useState("");
  const [boundAddress, setBoundAddress] = useState("");
  const db = SQLite.openDatabase('digit.db');
  const day = "'"+route.params.day+"'" //"'2024/08/23'";
  //const dataset = this.route.day //props.route.params.day// navigation.state.params.day;// this.props.navigation.state.params.day;
  //console.log(dataset);
  const params = route.params;
  console.log(params);
  const [collectionReport, setcollectionReport] = useState([]);
  
    let coll = [];
    db.transaction(tx=>{
      tx.executeSql("SELECT id,date,custNo,payMode,paidAmount FROM tblRcpt where date = "+day+" order by id DESC",
        null, (txt,results)=>{
          let len = results.rows.length;
          let billNo =0;
          let custNo =0;
          let paidAmt = 0;
          let payMod = '';
          let billDte="";
          //console.log(len)
            if (len>0){              
              for(let i =0;i<len;i++){
                let item = results.rows.item(i);
                billNo =  item.id;
                billDte = item.date;
                custNo =  item.custNo;
                payMod =  item.payMode;
                paidAmt = item.paidAmount;
                
                if (item.payMode === 'cash'){
                  payMod = 'C';
                }
                if (item.payMode === 'gpay'){
                    payMod = 'D';
                }
                //console.log(item)
                coll.push({billDte:item.date,billNo:item.id,custNo:item.custNo,payMod:item.payMode,paidAmt:item.paidAmount});
              }
              setcollectionReport(coll);
            }           
           
            //console.log(collectionReport)
        },(txt,error) => console.log(error)
      )
      
    })
    //db.closeAsync(); 

  const renderCollectionReport = ({item})=>{    
    return(
      <View style={{
        flexDirection:'row',
        borderBottomWidth:0.5,
        padding:2, 
        backgroundColor:'#fdfef4',
        height:40   
      }}>
        <Text style={{marginLeft:2,width:60,paddingLeft:2,paddingRight:2}}>{item.billNo}</Text>
        <Text style={{marginLeft:2,width:95,paddingRight:2.5}}>{item.billDte}</Text>
        <Text style={{marginLeft:2,width:75,paddingRight:2.5}}>{item.custNo}</Text>
        <Text style={{marginLeft:2,width:60,paddingRight:2.5}}>{item.payMod}</Text>
        <Text style={{textAlign:'right'}}>{item.paidAmt}</Text>        
      </View>

    )
  }

  return (
    <View style={{flex:1}}>
      <View style={{}}>
        <View style={{fontSize:10,height:50,paddingTop:10,paddingBottom:5,flexDirection:'row',borderBottomWidth:.25,backgroundColor: '#2a053a',}}>
          <Text style={{width:60,fontSize:11,paddingLeft:5, textAlign:'left',color:'white'}}>ID</Text>
          <Text style={{width:75,fontSize:11,paddingLeft:3, textAlign:'center',color:'white'}}>DATE</Text>
          <Text style={{width:75,fontSize:11,paddingRight:5,marginLeft:5,marginRight:5,borderRightWidth:0.25,color:'white'}}>CUSTOMER</Text>
          <Text style={{width:60,fontSize:11,marginLeft:10,borderRightWidth:0.25,color:'white'}}>MODE</Text>
          <Text style={{fontSize:11,paddingLeft:3, color:'white'}}>AMOUNT</Text>
        </View>
        <View style={{ paddingBottom:60}}>
          <FlatList style={{}} data={collectionReport} renderItem={renderCollectionReport} />
        </View>            
      </View>
      </View>
      )
    
}

Ответ или решение

Для решения проблемы бесконечного цикла в коде React Native, необходимо обратиться к основам работы хуков и управления состоянием в React, а именно к хуку useState, используемому в вашем компоненте Report. Давайте подробно разберем вашу ситуацию и предложим некоторые рекомендации.

Причина появления бесконечного цикла

Основная причина, по которой у вас возникает бесконечное выполнение console.log(params) и вызов setcollectionReport(coll) заключается в том, как React управляет состоянием и обновлением компонента. Ваша проблема возникает, когда каждое обновление состояния вызывает повторный рендер компонента, который в свою очередь снова вызывает эффект обновления состояния. Это происходит, потому что вызов setcollectionReport(coll) приводит к изменению состояния, которое пересоздает компонент, вызвав новый набор операций внутри функции компонента.

Как избежать бесконечного цикла

  1. Использование эффекта для управления побочными эффектами:
    Вместо того чтобы напрямую обновлять состояние внутри функции компонента, рекомендуется использовать хук useEffect. Это поможет вам контролировать, когда именно обновление состояния должно происходить.

  2. Внедрение зависимости:
    Оберните запрос к базе данных и обновление состояния в useEffect, чтобы работать с побочными эффектами и обеспечивать правильное выполнение кода.

Вот упрощенный пример, как можно обновить ваш код:

import React, { useEffect, useState } from 'react';
import { View, Text, FlatList } from 'react-native';
import * as SQLite from 'expo-sqlite';

function Report({ navigation, route }) {

  const [collectionReport, setcollectionReport] = useState([]);

  useEffect(() => {
    const db = SQLite.openDatabase('digit.db');
    const day = "'" + route.params.day + "'";

    db.transaction(tx => {
      tx.executeSql(
        "SELECT id, date, custNo, payMode, paidAmount FROM tblRcpt WHERE date = " + day + " ORDER BY id DESC",
        null,
        (tx, results) => {
          const len = results.rows.length;
          let coll = [];
          for (let i = 0; i < len; i++) {
            let item = results.rows.item(i);
            coll.push({
              billDte: item.date,
              billNo: item.id,
              custNo: item.custNo,
              payMod: item.payMode,
              paidAmt: item.paidAmount
            });
          }
          setcollectionReport(coll);
        },
        (tx, error) => console.error(error)
      );
    });
  }, [route.params.day]); // Запуск эффекта при изменении дня

  const renderCollectionReport = ({ item }) => (
    <View style={{
      flexDirection: 'row',
      borderBottomWidth: 0.5,
      padding: 2,
      backgroundColor: '#fdfef4',
      height: 40
    }}>
      <Text style={{ marginLeft: 2, width: 60, paddingLeft: 2, paddingRight: 2 }}>{item.billNo}</Text>
      <Text style={{ marginLeft: 2, width: 95, paddingRight: 2.5 }}>{item.billDte}</Text>
      <Text style={{ marginLeft: 2, width: 75, paddingRight: 2.5 }}>{item.custNo}</Text>
      <Text style={{ marginLeft: 2, width: 60, paddingRight: 2.5 }}>{item.payMod}</Text>
      <Text style={{ textAlign: 'right' }}>{item.paidAmt}</Text>
    </View>
  );

  return (
    <View style={{ flex: 1 }}>
      <FlatList
        data={collectionReport}
        renderItem={renderCollectionReport}
        keyExtractor={(item) => item.billNo.toString()}
      />
    </View>
  );
}

export default Report;

Заключение

Переход на использование useEffect может значительно улучшить управление состоянием в вашем компоненте и предотвратить бесконечные циклы. Таким образом, вы обеспечите более стабильную работу приложения и лучшее поведение интерфейса. Обратите внимание на зависимости в массиве зависимостей useEffect, чтобы избежать лишних вызовов и улучшить производительность.

Оцените материал
Добавить комментарий

Капча загружается...