javascript - 反应渲染循环运行两次
问题描述
我正在尝试用时刻制作简单的日历。它第一次加载完美,但是当单击上一个或下一个我的 for 循环在渲染运行两次时,这可能是问题
My project
https://stackblitz.com/edit/react-ts-itbzcd
public render() {
let day = this.props.date
for (let i = 0; i < 7; i++) {
this.days.push(
<Day key={day.toString()} date={day.date()} />
);
day = day.clone();
day.add(1, "day");
}
console.log(this.days)
return (
<tr key={this.days[0]}>
{this.days}
</tr>
);
}
完整的Calendar
组件:
import moment = require('moment');
import * as React from 'react'
import { DayNames, Week } from '.'
import styles from './Calendar.module.scss'
interface ICalendarProps {
}
interface ICalendarState {
dateObject: moment.Moment
showYearTable: boolean
}
export class Calendar extends React.Component<ICalendarProps, ICalendarState> {
constructor(props: ICalendarProps) {
super(props)
this.state = {
dateObject: moment(),
showYearTable: false
}
this.onNext = this.onNext.bind(this)
this.onPrev = this.onPrev.bind(this)
}
public render(): React.ReactElement<ICalendarProps> {
const datePicker =
<div className="datepicker-days">
<table className={styles.table}>
<thead>
<tr>
<th><span className="ms-Icon ms-Icon--ChevronLeft" title="Previous Month" onClick={this.onPrev}>Previous</span></th>
<th className={styles["picker-switch"]} data-action="pickerSwitch" colSpan={5} title="Select Month">
{this.month()}{" "} {this.year()}
</th>
<th><span className="ms-Icon ms-Icon--ChevronRight" title="Next Month" onClick={this.onNext}>Next</span></th>
</tr>
<tr>
<DayNames />
</tr>
</thead>
<tbody>
{this.renderWeeks()}
</tbody>
</table>
</div>
return (
<div className="datepicker">
{datePicker}
</div>
)
}
private month = () => {
return this.state.dateObject.format('MMMM')
}
private year = () => {
return this.state.dateObject.format("Y");
};
private onPrev = () => {
this.setState({
dateObject: this.state.dateObject.subtract(1, this.state.showYearTable === true ? "year" : "month")
});
};
private onNext = () => {
this.setState({
dateObject: this.state.dateObject.add(1, this.state.showYearTable === true ? "year" : "month")
});
};
private renderWeeks() {
let weeks = [];
let date = this.state.dateObject.clone().startOf("month").add("w").day("Sunday");
let done = false;
let count = 0;
let monthIndex = date.month();
while (!done) {
weeks.push(
<Week key={date.toString()} date={date.clone()} />
)
date.add(1, "w");
done = count++ > 2 && monthIndex !== date.month();
monthIndex = date.month();
}
return weeks
}
}
解决方案
我有你的问题。您遇到此问题是因为您如何在函数上设置组件的key
prop 。1 周从一个月到另一个重复,因此当您更改月份时,2 s 组件以相同的道具结束。React,何时重新渲染您的组件,查看并回收该组件。Week
renderWeeks
Week
key
做这样的事情可以解决你的问题:
private renderWeeks() {
let weeks = [];
let date = this.state.dateObject.clone().startOf("month").add("w").day("Sunday");
let done = false;
let count = 0;
let monthIndex = date.month();
while (!done) {
weeks.push(
<Week key={Math.floor(Math.random() * 10000)} date={date.clone()} />
)
date.add(1, "w");
done = count++ > 2 && monthIndex !== date.month();
monthIndex = date.month();
}
return weeks
}
但这可能会降低您的重新渲染性能,您需要处理您的Calendar
组件以避免他在第一周重新渲染,或者您可以使用加载组件(糟糕的 UX)清除所有日历状态。有很多选择。
我的解决方案是将周存储在Calendar
组件状态中,然后仅用新的周更新它。
推荐阅读
- list - 将每个项目与列表的其余项目进行比较
- sql-server - 必须用更新百分比声明标量变量
- azure - 是否可以通过 ARM 模板在 Azure SQL 中预配非管理用户?
- java - 在 Spring Boot 中创建一个 Couchbase 配置类,使用数据表单 application.properties?
- algorithm - 算法的最佳情况
- mongodb - 如何检索 mongoDB 集群中的所有数据库名称?
- javascript - 谷歌脚本或语句
- c# - DeleteMessageAsync()不删除SQS队列.Net Core中的消息
- python - 在 for 循环声明中发生未知故障。我该如何解决?
- oracle11g - oracle 11g application express接口虚拟列计算总销售额