【问题标题】:React Native: Too many re-renders. React limits the number of renders to prevent an infinite loopReact Native:重新渲染太多。 React 限制渲染次数以防止无限循环
【发布时间】:2021-08-24 16:12:27
【问题描述】:

我刚刚在 YouTube 上完成了 React Native 的待办事项列表教程,我决定尝试向其中添加一些功能,例如确认模式。问题是每当我尝试将任何内容传递到模态“完成任务”onPress 时,我都会收到此错误:

错误:重新渲染过多。 React 限制渲染次数以防止无限循环。

import React, { useState } from "react";
import {
  KeyboardAvoidingView,
  Platform,
  StyleSheet,
  Text,
  TextInput,
  Keyboard,
  TouchableOpacity,
  View,
} from "react-native";
import Modal from "react-native-modal";
import Task from "./components/Task";

export default function App() {
  const [task, setTask] = useState();
  const [taskItems, setTaskItems] = useState([]);
  const [modalVisable, setModalVisable] = useState(false);
  const [itemToDelete, setItemToDelete] = useState();

  const handleAddTask = () => {
    Keyboard.dismiss();
    setTaskItems([...taskItems, task]);
    setTask(null);
  };

  const completeTask = (index) => {
    let itemsCopy = [...taskItems];
    itemsCopy.splice(index, 1);
    setTaskItems(itemsCopy);
  };

  const closeModal = (itemToDelete) => {
    completeTask(itemToDelete)
    setModalVisable(false);
  };

  const handleRemoveTask = (index) => {
    setModalVisable(true);
  };

  

  return (
    <View style={styles.container}>
      <View style={styles.tasksWrapper}>
        <Text style={styles.sectionTitle}>Your Tasks</Text>

        <View style={styles.items}>
          {taskItems.map((item, index) => {
            return (
              <TouchableOpacity
                key={index}
                onPress={() => {
                  handleRemoveTask(index);
                  
                }}
              >
                <Task text={item} />
              </TouchableOpacity>
            );
          })}
        </View>
      </View>

      <KeyboardAvoidingView
        behavior={Platform.OS === "ios" ? "padding" : "height"}
        style={styles.writeTaskWrapper}
      >
        <TextInput
          style={styles.input}
          placeholder={"Add a task!"}
          value={task}
          onChangeText={(text) => setTask(text)}
        />

        <TouchableOpacity onPress={() => handleAddTask()}>
          <View style={styles.addWrapped}>
            <Text style={styles.addText}>+</Text>
          </View>
        </TouchableOpacity>
      </KeyboardAvoidingView>
      <View style={styles.modalWrapper}>
        <Modal
          style={styles.modal}
          isVisible={modalVisable}
          onBackdropPress={closeModal}
        >
          <Text style={styles.modalText}>Test Modal</Text>
          <TouchableOpacity style={styles.closeButton} onPress={closeModal(itemToDelete)}>
            <Text style={styles.modalText}>
              Complete Task
            </Text>
          </TouchableOpacity>
        </Modal>
      </View>
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: "#E8EAED",
  },
  tasksWrapper: {
    paddingTop: 80,
    paddingHorizontal: 20,
  },
  sectionTitle: {
    fontSize: 24,
    fontWeight: "bold",
  },
  items: {
    marginTop: 30,
  },
  writeTaskWrapper: {
    position: "absolute",
    bottom: 50,
    width: "100%",
    flexDirection: "row",
    justifyContent: "space-around",
    alignItems: "center",
  },
  input: {
    paddingVertical: 15,
    paddingHorizontal: 15,
    backgroundColor: "#FFF",
    borderRadius: 60,
    borderColor: "#C0C0C0",
    borderWidth: 1,
    textAlign: "center",
    width: 300,
  },
  addWrapped: {
    width: 60,
    height: 60,
    backgroundColor: "#FFF",
    borderRadius: 60,
    borderColor: "#C0C0C0",
    borderWidth: 1,
    justifyContent: "center",
    alignItems: "center",
  },
  addText: {},
  modalWrapper: {},
  modal: {
    backgroundColor: "#FFF",
    maxHeight: 250,
  },
  modalText: {
    fontWeight: "bold",
    textAlign: "center",
    justifyContent: "center",
  },
  closeButton: {
    justifyContent: "center",
    position: "absolute",
    width: "100%",
    height: 30,
    bottom: 0,
    backgroundColor: "#BE33FF",
  },
});

我已经尽力尝试了一些我能想到的变通办法,但是很遗憾,我找不到方法。如果您有任何想法,我会感谢您的帮助,谢谢 Lachie。

【问题讨论】:

    标签: reactjs react-native


    【解决方案1】:

    我觉得这条线很可疑

    onPress={closeModal(itemToDelete)}
    

    您在每个渲染上调用closeModal函数。

    onPress 期望在按下任何内容时调用一个函数。 您应该将其替换为

    onPress={function() { closeModal(itemToDelete);}
    

    或简写版本

    onPress={() => { closeModal(itemToDelete) }
    

    【讨论】:

      【解决方案2】:

      你的错误在这里:

      <TouchableOpacity style={styles.closeButton} onPress={closeModal(itemToDelete)}>
      

      渲染后立即调用closeModal(itemToDelete) 属性,它本身调用completeTask(itemToDelete),然后调用setTaskItems(itemsCopy)。 最后一个函数导致无限渲染循环。

      您可能想要的是在用户单击TouchableOpacity 后调用closeModal(itemToDelete),如下所示:

      <TouchableOpacity style={styles.closeButton} onPress={() => closeModal(itemToDelete)}>
      

      【讨论】:

        猜你喜欢
        • 2021-02-26
        • 1970-01-01
        • 2020-09-22
        • 2020-08-07
        • 2021-07-01
        • 2021-05-17
        • 2021-02-04
        相关资源
        最近更新 更多