You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React Native中DatePicker出现Maximum update depth exceeded警告求助

解决React Native Modern DatePicker无限更新循环问题

问题根源

  1. 重复回调触发循环更新:同时给DatePicker绑定onDateChange和onSelectedChange两个回调,前者更新placeholderDate,后者更新book.date。两个状态的更新都会触发组件重新渲染,DatePicker渲染后又会再次触发回调,形成无限循环,导致「Maximum update depth exceeded」警告。
  2. 不必要的重复计算:initialDate在组件每次渲染时都会重新调用getFormatedDate生成,造成性能浪费。

修复方案

  1. 合并日期选择逻辑,用一个函数同时更新book.date和placeholderDate,只保留一个DatePicker回调。
  2. 用useMemo缓存initialDate,避免重复计算。
  3. 移除多余的回调函数和属性,简化组件逻辑。

修改后的完整代码

import React, { useEffect, useRef, useState, useMemo } from "react";
import {
  View,
  Text,
  TextInput,
  Pressable,
  Alert,
  TouchableOpacity,
  Modal,
} from "react-native";
import { appFirebase } from "../../../credentials.js";
import { getFirestore, collection, addDoc } from "firebase/firestore";
import { styles } from "../../../styles/styles";
import DatePicker from "react-native-modern-datepicker";
import { getFormatedDate } from "react-native-modern-datepicker";

const db = getFirestore(appFirebase);

const Create = (props: {
  navigation: { navigate: (arg0: string) => void };
}) => {
  // 捕获输入框值
  const [book, setBook] = useState({
    title: "",
    author: "",
    genre: "",
    date: "",
  });
  const handleInputOnChangeText = (name: string, value: string) =>
    setBook({ ...book, [name]: value });
  
  // 模态框显示切换
  const [visible, setVisible] = useState(false);
  const handleToggle = () => setVisible(!visible);
  
  // 缓存初始日期,避免重复计算
  const initialDate = useMemo(() => getFormatedDate(new Date(), "YYYY/MM/DD"), []);
  
  const [placeholderDate, setPlaceholderDate] = useState(
    "Fecha de publicación"
  );
  
  // 合并日期选择逻辑:同时更新book.date和placeholderDate
  const handleDateSelect = (selectedDate: string) => {
    setBook(prev => ({ ...prev, date: selectedDate }));
    setPlaceholderDate(selectedDate);
  };

  // 判断提交按钮是否禁用
  const [isDisabled, setIsDisabled] = useState(true);
  useEffect(() => {
    const areFieldsFilled =
      book.title.trim() !== "" &&
      book.author.trim() !== "" &&
      book.genre.trim() !== "" &&
      book.date.trim() !== "";

    setIsDisabled(!areFieldsFilled);
  }, [book]);
  
  // 提交数据到Firebase
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState(null);
  const handleSubmitSavedBook = async () => {
    try {
      setLoading(true);
      const docAdded = await addDoc(collection(db, "library"), {
        ...book,
      });
      if (!docAdded) {
        throw new Error("You got a problem adding book");
      }
      console.log("Document written with ID:", docAdded.id);
      Alert.alert("Your book has been saved!");
      props.navigation.navigate("Library");
    } catch (err: any) {
      if (err instanceof Error) {
        console.error(err.message);
      }
      if (err instanceof SyntaxError) {
        console.error(err.message);
      }
      if (err instanceof TypeError) {
        console.error(err.message);
      }
      setError(err);
    } finally {
      setLoading(false);
    }
  };
  
  // 重置表单
  const handleResetForm = () => {
    setBook({ title: "", author: "", genre: "", date: "" });
    setPlaceholderDate("Fecha de publicación");
  };
  
  // 自动聚焦第一个输入框
  const inputRef = useRef<TextInput>(null);
  useEffect(() => {
    inputRef.current?.focus();
  }, []);
  
  return (
    <>
      <View style={styles.containerCenter}>
        <Text style={styles.titleText}>AÑADE INFORMACIÓN</Text>
        {loading && <Text>Is Loading...</Text>}
        {error && (
          <View>
            <Text>{`${error}`}</Text>
          </View>
        )}
        <View>
          <TextInput
            placeholder="Titulo"
            ref={inputRef}
            onChangeText={(value) =>
              handleInputOnChangeText("title", value.toLocaleUpperCase())
            }
            value={book.title}
          />

          <TextInput
            placeholder="Autor"
            onChangeText={(value) => handleInputOnChangeText("author", value)}
            value={book.author}
          />

          <TextInput
            placeholder="Género"
            onChangeText={(value) => handleInputOnChangeText("genre", value)}
            value={book.genre}
          />

          <TouchableOpacity onPress={handleToggle}>
            <Text>{placeholderDate}</Text>
          </TouchableOpacity>
          <Modal animationType="fade" transparent={true} visible={visible}>
            <View style={styles.containerCenter}>
              <View style={styles.containerModal}>
                <DatePicker
                  mode="calendar"
                  maximumDate={initialDate}
                  selected={book.date}
                  // 只保留一个回调处理日期选择
                  onDateChange={handleDateSelect}
                  options={{
                    backgroundColor: "#080516",
                    textHeaderColor: "#469ab6",
                    textDefaultColor: "white",
                    selectedTextColor: "white",
                    mainColor: "#469ab6",
                    textSecondaryColor: "white",
                    borderColor: "#7a92a51a",
                  }}
                />
                <TouchableOpacity style={styles.button} onPress={handleToggle}>
                  <Text style={styles.buttonText}>Cerrar</Text>
                </TouchableOpacity>
              </View>
            </View>
          </Modal>
        </View>
        <View>
          <Pressable
            style={styles.button}
            onPress={handleSubmitSavedBook}
            disabled={isDisabled}
          >
            <Text style={styles.buttonText}>Guardar</Text>
          </Pressable>
          <Pressable style={styles.button} onPress={handleResetForm}>
            <Text style={styles.buttonText}>Restablecer</Text>
          </Pressable>
          <Pressable
            style={styles.button}
            onPress={() => props.navigation.navigate("Library")}
          >
            <Text style={styles.buttonText}>Volver</Text>
          </Pressable>
        </View>
      </View>
    </>
  );
};

export { Create };

关键修改点

  • 新增useMemo缓存initialDate,避免每次渲染重复生成日期字符串。
  • 移除handleInputOnChangeDate和handleChangeInitialDate,替换为handleDateSelect函数,同时更新book.date和placeholderDate。
  • DatePicker只保留onDateChange回调,移除onSelectedChange,避免重复触发状态更新。
  • 重置表单时同时重置placeholderDate为初始提示文本,提升用户体验。

内容的提问来源于stack exchange,提问作者MLT93

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 08:14:54