英文:
Re-render infinity in react component
问题
当您写成 date: new Date()
时,组件会无限重新渲染的原因是,每次组件重新渲染时,new Date()
都会创建一个新的 Date
对象,这个新对象与之前的对象不相等。这导致 React 认为组件的状态发生了变化,因此触发了重新渲染,然后又创建了新的 Date
对象,这一过程不断重复,导致无限重新渲染的循环。
而当您写成 date: new Date().toISOString().slice(0, 10)
时,new Date().toISOString().slice(0, 10)
只会在组件首次渲染时计算一次,并且返回一个字符串,表示当前日期的年、月、日部分。这个字符串不会随着组件的重新渲染而改变,因此不会触发无限重新渲染的问题。
为了解决无限重新渲染的问题,您可以使用 React 的 useMemo
钩子来确保 initialValues
对象中的 date
属性只在组件首次渲染时计算一次,而不会在每次重新渲染时重新计算。例如:
import { useFormik } from 'formik';
import React, { useMemo } from 'react';
const MyForm = () => {
const initialValues = useMemo(() => ({
date: new Date().toISOString().slice(0, 10),
// other form fields...
}), []); // Empty dependency array ensures this runs only once
const onSubmit = (values) => {
// Handle form submission
console.log(values);
};
const formik = useFormik({
initialValues,
onSubmit,
});
return (
<form onSubmit={formik.handleSubmit}>
<div>
<label htmlFor="date">Date:</label>
<input
type="date"
id="date"
name="date"
onChange={formik.handleChange}
value={formik.values.date}
/>
</div>
{/* other form fields... */}
<button type="submit">Submit</button>
</form>
);
};
export default MyForm;
通过这种方式,initialValues
只会在组件首次渲染时计算一次,从而解决了无限重新渲染的问题。
英文:
I have the following simple react component
import { useFormik } from 'formik';
import React from 'react';
const MyForm = () => {
const initialValues = {
date: new Date().toISOString().slice(0, 10), // Get the current date in YYYY-MM-DD format
// other form fields...
};
const onSubmit = (values) => {
// Handle form submission
console.log(values);
};
const formik = useFormik({
initialValues,
onSubmit,
});
return (
<form onSubmit={formik.handleSubmit}>
<div>
<label htmlFor="date">Date:</label>
<input
type="date"
id="date"
name="date"
onChange={formik.handleChange}
value={formik.values.date}
/>
</div>
{/* other form fields... */}
<button type="submit">Submit</button>
</form>
);
};
export default MyForm;
My question is why when I'm writing date: new Date()
the component gots re-render infinitely, on the other hand when I write date: new Date().toISOString().slice(0, 10)
it works fine. what is the reason behind that?
答案1
得分: 0
在JavaScript中,有两种类型的变量 - 引用类型和原始类型。
这个表达式 new Date().toISOString().slice(0, 10)
返回字符串 - 原始类型,所以组件不会无限重新渲染,因为字符串值的比较保持一致。
但是在 new Date()
的情况下,组件会无限重新渲染,因为它在每次渲染时创建一个新的日期对象。对象是按引用进行比较,即使日期和时间的值相同,新的日期对象被视为与之前的不同。
为了避免无限重新渲染的问题,你需要使用一个一致的值作为初始状态,比如通过 new Date().toISOString().slice(0, 10)
获取的字符串格式,就像你在你的代码中所做的那样。
英文:
In javascript, there are two types of variables - reference and primitive.
This expression new Date().toISOString().slice(0, 10)
returns string - primitive type so the component doesn't re-render infinitely because the comparison of the string values remains consistent.
But in the case of new Date()
, the component re-renders infinitely because it creates a new Date object every render. objects are compared by reference, the new Date object is considered different from the previous one, even if the date and time values are the same.
To avoid the infinite re-rendering issue, you need to use a consistent value for the initial state, such as the string format obtained by new Date().toISOString().slice(0, 10)
, as you have done in your code.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论