Expo SQLite 渲染无限数量的组件

Posted

技术标签:

【中文标题】Expo SQLite 渲染无限数量的组件【英文标题】:Expo SQLite rendering infinite number of component 【发布时间】:2021-10-03 03:23:23 【问题描述】:

我目前正在使用 expo 及其 sqlite 数据库编写一个反应原生应用程序。 我从我的数据库中获取一些数据,然后呈现一些组件,一个用于我的选择查询的每一行。

我遇到的问题是,它不是用正确的数据渲染正确数量的组件,而是渲染无限数量的没有数据的组件。

代码(奇怪的渲染发生在 elem.map 中):

import React, useCallback, useEffect, useState from 'react';
import Picker, Text, TextInput, TouchableOpacity, View from "react-native";
import * as SQLite from "expo-sqlite";
import useFocusEffect from "@react-navigation/native";
import Arbre from "../Localisation/Arbre";
import Styles from "../Styles";
import  Ionicons  from '@expo/vector-icons';
import  AntDesign  from '@expo/vector-icons';

const db = SQLite.openDatabase('Agora');

const addDesignation = (n, s, c, sc, d) => 
    console.log(n+'\n'+s+'\n'+c+'\n'+sc+'\n'+d);
    db.transaction((tx) => 
        let idp;
        tx.executeSql("SELECT * FROM CURRENTID ", [], (tx, rs) => 
            idp=rs.rows.item(0).currentCompId;
            tx.executeSql("INSERT INTO ELEMENT (nom, strate, classe, sousClasse, denom, idComp) VALUES (?,?,?,?,?,?)", [n, s, c, sc, d, idp],
                (tx, rs) => , (tx, e) => console.log(e));
        )
    )



const Designation = (navigation) => 
    const [elem, setElem] = useState([]);
    const [nom, setNom] = useState();
    const [strate, setStrate] = useState();
    const [classe, setClasse] = useState();
    const [sc, setSc] = useState();
    const [denom, setDenom] = useState();

    const selectElem = (comp) => 
        db.transaction( (tx) => 
            tx.executeSql("SELECT * FROM ELEMENT WHERE idCOmp = ?", [comp], (tx, rs) => 
                let res = [];
                for (let i = 0; i<rs.rows.length; i++) 
                    console.log(rs.rows.item(i).nom);
                    res.push(rs.rows.item(i));
                
                setElem(res);
            )
        );
    ;

    useFocusEffect(() => 
        db.transaction((tx) => 
            let idp;
            tx.executeSql("SELECT * FROM CURRENTID ", [], (tx, rs) => 
                idp=rs.rows.item(0).currentCompId;
                selectElem(idp);
            )
        )

    );

    return (
        <>
            <View style=flexDirection: "row", flex:1, width: '100%', height: '100%'>
                <Arbre/>
                <View style=flex: 2>
                    <View style=backgroundColor: 'gray', flex:2, flexDirection: "column">
                        
                            elem.map(value => 
                                console.log('taille : '+elem.length);
                                return(
                                    <View key=value.idElem style=flexDirection: "row">
                                        <TextInput
                                            style=Styles.designPicker
                                            onChangeText=(n) => 
                                            value=value.nom
                                            placeholder="Nom de l'élément"
                                        />
                                        <Picker
                                            style=Styles.designPicker
                                            selectedValue=value.strate
                                            onValueChange=(itemValue, itemIndex) =>
                                        >
                                            <Picker.Item label='test' value='test'/>
                                        </Picker>
                                        <Picker
                                            style=Styles.designPicker
                                            selectedValue=value.classe
                                            onValueChange=(itemValue, itemIndex) => 
                                        >
                                            <Picker.Item label='test' value='test'/>
                                        </Picker>
                                        <Picker
                                            style=Styles.designPicker
                                            selectedValue=value.sousClasse
                                            onValueChange=(itemValue, itemIndex) => 
                                        >
                                            <Picker.Item label='test' value='test'/>
                                        </Picker>
                                        <Picker
                                            style=Styles.designPicker
                                            selectedValue=value.denom
                                            onValueChange=(itemValue, itemIndex) => 
                                        >
                                            <Picker.Item label='test' value='test'/>
                                        </Picker>
                                        <TouchableOpacity
                                            onPress=addDesignation
                                        >
                                            <AntDesign name="pluscircle" size=24 color="black"/>
                                        </TouchableOpacity>
                                    </View>
                                );
                            )
                        

                        <View style=flexDirection: "row">
                            <TextInput
                                style=Styles.designPicker
                                onChangeText=(n) => setNom(n)
                                value=nom
                                placeholder="Nom de l'élément"
                            />
                            <Picker
                                style=Styles.designPicker
                                selectedValue=strate
                                onValueChange=(itemValue, itemIndex) =>setStrate(itemValue)
                            >
                                <Picker.Item label='test' value='test'/>
                            </Picker>
                            <Picker
                                style=Styles.designPicker
                                selectedValue=classe
                                onValueChange=(itemValue, itemIndex) => setClasse(classe)
                            >
                                <Picker.Item label='test' value='test'/>
                            </Picker>
                            <Picker
                                style=Styles.designPicker
                                selectedValue=sc
                                onValueChange=(itemValue, itemIndex) => setSc(itemValue)
                            >
                                <Picker.Item label='test' value='test'/>
                            </Picker>
                            <Picker
                                style=Styles.designPicker
                                selectedValue=denom
                                onValueChange=(itemValue, itemIndex) => setDenom(itemValue)
                            >
                                <Picker.Item label='test' value='test'/>
                            </Picker>
                            <TouchableOpacity
                                onPress=addDesignation(nom, strate, classe, sc, denom)
                            >
                                <AntDesign name="pluscircle" size=24 color="black"/>
                            </TouchableOpacity>
                        </View>

                    </View>
                </View>

            </View>
        </>
    );


export default Designation;

【问题讨论】:

【参考方案1】:

尝试添加一个空的依赖数组,这应该可以修复循环。

 useFocusEffect(() => 
        db.transaction((tx) => 
            let idp;
            tx.executeSql("SELECT * FROM CURRENTID ", [], (tx, rs) => 
                idp=rs.rows.item(0).currentCompId;
                selectElem(idp);
            )
        )

    , []);

【讨论】:

使用 useFocusEffect,我需要使用 useCallback,然后在 useCallback 末尾有依赖数组,但是当我这样做时,我得到“无效的挂钩调用”【参考方案2】:

我遇到的问题是我在 touchableopacity 上写了 addDesignation 而不是 () => addDesignation,导致方法每秒添加一次

【讨论】:

以上是关于Expo SQLite 渲染无限数量的组件的主要内容,如果未能解决你的问题,请参考以下文章

ReactJs 上的无限循环渲染组件

避免在反应组件中无限重新渲染

Vue 组件中的“组件渲染函数中可能存在无限更新循环”警告

如何从无限重新渲染中停止反应组件

组件渲染函数中的Vue无限更新循环

使用Vue组件渲染功能时的无限循环