简体   繁体   English

我的 React Native Expo 应用程序中的无限循环在哪里?

[英]Where is the infinite loop in my React Native Expo App?

In my app, I made my own checkboxes.在我的应用程序中,我创建了自己的复选框。 There are two styles available: multi choices or single choice.有两种样式可供选择:多选或单选。 If the option if on a single choice, only one checkbox can be activated at the time.如果该选项是单项选择,则一次只能激活一个复选框。

When I click on a checkbox of the single kind (multi == false), the app throws me an error当我单击单一类型的复选框 (multi == false) 时,应用程序会向我抛出一个错误

"Invariant Violation: Too many re-renders". “不变违规:太多重新渲染”。

I don't see where I would have an infinite loop in my code...我没有看到我的代码中哪里会有无限循环......

Here is an example of my code :这是我的代码示例:

import React, { useState, useEffect } from "react";
import { View, SafeAreaView, Text, ScrollView, StyleSheet } from "react-native";
import { generalStyles } from "@gym-app/styles/general";
import { useTranslation } from "react-i18next";
import persistent from "@gym-app/database/persistent";
import CheckboxRow from "../../components/workout/exercises/filters/CheckboxRow";
import tdb from "@gym-app/translation/object";
import Checkbox from "../../components/workout/exercises/filters/Checkbox";

export default function ExercisesFilterScreen() {
  const { t } = useTranslation();
  const [equipments, setEquipments] = useState({});
  const [selectedEquipments, setSelectedEquipments] = useState({});
  const [order, setOrder] = useState("");
  if (Object.values(equipments).length == 0) {
    persistent.transaction(tx => {
      tx.executeSql(
        "SELECT * FROM equipment",
        [],
        (t, s) => {
          setEquipments(s.rows._array);
        },
        (t, e) => {
          console.log(e);
        }
      );
    });
  }

  useEffect(() => {
    alert(order);
  });

  return (
    <SafeAreaView style={{ flex: 1 }}>
      <ScrollView
        style={[
          generalStyles.contentContainer,
          { flex: 1, backgroundColor: "#ffb623" }
        ]}
      >
        <Text
          style={{
            fontSize: 30,
            fontWeight: "bold",
            color: "#ffffff",
            textAlign: "center"
          }}
        >
          {t("general.filters").toUpperCase()}
        </Text>
        <View style={{ marginTop: 10 }}>
          <Text style={styles.optionTitle}>
            {t("exercise.availableEquipment").toUpperCase()}
          </Text>
          {Object.values(equipments).map(equipment => {
            return (
              <CheckboxRow
                key={equipment.id}
                selected={selectedEquipments}
                select={setSelectedEquipments}
                multi={true}
                id={equipment.id}
              >
                {tdb(equipment, "name")}
              </CheckboxRow>
            );
          })}
          <Text style={styles.optionTitle}>
            {t("exercise.order").toUpperCase()}
          </Text>
          <CheckboxRow
            selected={order}
            select={setOrder}
            multi={false}
            id="asc"
          >
            {t("exercise.easyToHard")}
          </CheckboxRow>
          <CheckboxRow
            selected={order}
            select={setOrder}
            multi={false}
            id="desc"
          >
            {t("exercise.hardToEasy")}
          </CheckboxRow>
        </View>
      </ScrollView>
    </SafeAreaView>
  );
}

const styles = StyleSheet.create({
  optionTitle: {
    marginBottom: 6,
    fontSize: 24,
    fontWeight: "bold",
    color: "#ffffff",
    textAlign: "left"
  }
});

Here is the CheckboxRow code:这是 CheckboxRow 代码:

import React, { useState } from "react";
import { TouchableOpacity, Text, StyleSheet } from "react-native";
import Checkbox from "./Checkbox";

export default function CheckboxRow(props) {
  const [checked, setChecked] = useState(false);

  if (props.multi == false) {
    if (props.selected == props.id) {
      setChecked(false);
    }
  }

  return (
    <TouchableOpacity
      style={styles.row}
      onPress={() => {
        var id = props.id;
        var selected = props.selected;
        var s = selected;
        if (props.multi == true) {
          if (s[id] == undefined) {
            s[id] = id;
          } else {
            delete s[id];
          }
        } else {
          if (s == id) {
            s = undefined;
          } else {
            s = id;
          }
        }
        props.select(s);
        console.log(props.select);
        setChecked(!checked);
      }}
    >
      <Checkbox checked={checked} />
      <Text style={styles.rowText}>{props.children}</Text>
    </TouchableOpacity>
  );
}

const styles = StyleSheet.create({
  row: {
    flexDirection: "row",
    alignItems: "center",
    marginBottom: 10
  },
  rowText: {
    fontSize: 26,
    color: "white",
    marginLeft: 6,
    fontWeight: "700"
  }
});

You should not call any async method inside render scope I think this is because of 2 reasons.你不应该在渲染范围内调用任何异步方法我认为这是因为两个原因。 either your sql query is running on each render or checkbox updating state.您的 sql 查询在每个渲染或复选框更新状态上运行。 make sure your sql query dont run again and again if equipments are empty.如果设备为空,请确保您的 sql 查询不会一次又一次地运行。

import React, { useState, useEffect } from "react";
import { View, SafeAreaView, Text, ScrollView, StyleSheet } from "react-native";
import { generalStyles } from "@gym-app/styles/general";
import { useTranslation } from "react-i18next";
import persistent from "@gym-app/database/persistent";
import CheckboxRow from "../../components/workout/exercises/filters/CheckboxRow";
import tdb from "@gym-app/translation/object";
import Checkbox from "../../components/workout/exercises/filters/Checkbox";

export default function ExercisesFilterScreen() {
  const { t } = useTranslation();
  const [equipments, setEquipments] = useState({});
  const [selectedEquipments, setSelectedEquipments] = useState({});
  const [order, setOrder] = useState("");

 //use useeffect for side effects
useEffect(()=> {
 if (Object.values(equipments).length == 0) {
    persistent.transaction(tx => {
      tx.executeSql(
        "SELECT * FROM equipment",
        [],
        (t, s) => {
          setEquipments(s.rows._array);
        },
        (t, e) => {
          console.log(e);
        }
      );
    });
  }

},[equipments])

  useEffect(() => {
    alert(order);
  });

  return (
    <SafeAreaView style={{ flex: 1 }}>
     ...
    </SafeAreaView>
  );
}

Also in checkbox component you can use useEffect for updating state同样在复选框组件中,您可以使用 useEffect 来更新状态

export default function CheckboxRow(props) {
  const [checked, setChecked] = useState(false);

  useEffect(()=>{
  if (props.multi == false) {
    if (props.selected == props.id) {
      setChecked(false);
    }
  }
 },[props.multi, props.selected])

  return (
    <TouchableOpacity>
   ...
    </TouchableOpacity>
  );
}

and finally check your dependencies to useEffect hook accordingly最后检查您的依赖项以相应地使用效果钩子

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM