Вопрос или проблема
Ниже приведен мой код в небольшом проекте 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)
приводит к изменению состояния, которое пересоздает компонент, вызвав новый набор операций внутри функции компонента.
Как избежать бесконечного цикла
-
Использование эффекта для управления побочными эффектами:
Вместо того чтобы напрямую обновлять состояние внутри функции компонента, рекомендуется использовать хукuseEffect
. Это поможет вам контролировать, когда именно обновление состояния должно происходить. -
Внедрение зависимости:
Оберните запрос к базе данных и обновление состояния в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
, чтобы избежать лишних вызовов и улучшить производительность.