Mir*_*dze 10 reactjs react-hooks
我正在创建一个 DatePicker 并使用 useState 钩子来管理它的可见性。在 div 单击时,我添加了更改值的事件侦听器,但它没有按我预期的那样工作。它仅在第一次起作用,因此初始值更改为 true,但在第二次和第三次单击时,此值保持为 true,并且 DatePicker 在单击时保持可见。
这是日期选择器
import React, { useState } from 'react';
import OutsideClickHandler from 'react-outside-click-handler';
import { renderInfo, getWeeksForMonth } from './utils';
import {
renderMonthAndYear,
handleBack,
handleNext,
weekdays,
} from '../../utils';
const DatePicker = ({
isOpen,
setIsOpen,
selected,
setSelected,
dayClick,
dayClass,
}) => {
const startDay = new Date().setHours(0, 0, 0, 0);
const [current, setCurrent] = useState(new Date(startDay));
const weeks = getWeeksForMonth(current.getMonth(), current.getFullYear());
function handleClick(date) {
if (date > startDay) {
setSelected(date);
setCurrent(date);
setIsOpen(false);
if (dayClick) {
dayClick(date);
}
}
}
return (
<div className="DatePicker-container">
<div
tabIndex="0"
role="button"
className="DatePicker-info"
onKeyPress={e => {
if (e.which === 13) {
setIsOpen(!isOpen);
}
}}
onClick={e => {
setIsOpen(!isOpen);
}}
>
{renderInfo(selected)}
</div>
{isOpen && (
<OutsideClickHandler onOutsideClick={() => setIsOpen(false)}>
<div className="DatePicker">
<div className="DatePicker__header">
<span
role="button"
onClick={() => handleBack(current, setCurrent)}
className="triangle triangle--left"
/>
<span className="DatePicker__title">
{renderMonthAndYear(current)}
</span>
<span
role="button"
onClick={() => handleNext(current, setCurrent)}
className="triangle triangle--right"
/>
</div>
<div className="DatePicker__weekdays">
{weekdays.map(weekday => (
<div
key={weekday}
className="DatePicker__weekday"
>
{weekday}
</div>
))}
</div>
{weeks.map((week, index) => (
<div
role="row"
key={index}
className="DatePicker__week"
>
{week.map((date, index) =>
date ? (
<div
role="cell"
key={index}
onClick={() => handleClick(date)}
className={dayClass(date)}
>
{date.getDate()}
</div>
) : (
<div
key={index}
className="DatePicker__day--empty"
/>
),
)}
</div>
))}
</div>
</OutsideClickHandler>
)}
</div>
);
};
export default DatePicker;
Run Code Online (Sandbox Code Playgroud)
其中使用两个 DateRangePicker。
import React, { useState } from 'react';
import DatePicker from './DatePicker';
import DatePickerContext from './DatePickerContext';
import './DatePicker.scss';
const DateRangePicker = () => {
const startDay = new Date().setHours(0, 0, 0, 0);
const [isOpen, setIsOpen] = useState(false);
const [isSecondOpen, setIsSecondOpen] = useState(false);
const [selected, setSelected] = useState(new Date(startDay));
const [secondSelected, setSecondSelected] = useState(new Date(startDay));
function dayClass(date) {
if (
selected.getTime() === date.getTime() ||
(date >= selected && date <= secondSelected)
) {
return 'DatePicker__day DatePicker__day--selected';
}
if (date < startDay || date < selected) {
return 'DatePicker__day DatePicker__day--disabled';
}
return 'DatePicker__day';
}
function dayClick(date) {
setSecondSelected(date);
setIsSecondOpen(true);
}
return (
<DatePickerContext.Provider>
<div className="DatePicker-wrapper">
<DatePicker
key={1}
isOpen={isOpen}
setIsOpen={setIsOpen}
selected={selected}
setSelected={setSelected}
dayClick={dayClick}
dayClass={dayClass}
/>
<DatePicker
key={2}
isOpen={isSecondOpen}
setIsOpen={setIsSecondOpen}
selected={secondSelected}
setSelected={setSecondSelected}
dayClass={dayClass}
/>
</div>
</DatePickerContext.Provider>
);
};
export default DateRangePicker;
Run Code Online (Sandbox Code Playgroud)
Apr*_*ion 20
a)当下一个状态依赖于前一个(== 当前)状态时,使用功能更新确保使用正确的“当前”值是一个很好的做法:
setIsOpen(currentIsOpen => !currentIsOpen)
Run Code Online (Sandbox Code Playgroud)
b) 当下一个状态被为同一事件执行的多个处理程序更新时,很难推断下一个状态。以下 2 个处理程序可能会在同一次点击中执行(第一个 div 是“外部”):
<div ... onClick={e => setIsOpen(!isOpen)}>
<OutsideClickHandler onOutsideClick={() => setIsOpen(false)}>
Run Code Online (Sandbox Code Playgroud)
如果onOutsideClick首先执行,然后 React 使用 重新渲染isOpen=false,然后onClick第二次执行,它会isOpen=true根据您的观察进行设置- 我不知道重新渲染是如何发生的,但可能OutsideClickHandler正在做一些邪恶的事情,或者您的代码比在问题¯\_(?)_/¯
仅强制执行 1 个事件处理程序:
<OutsideClickHandler onOutsideClick={(e) => {
e.stopPropagation();
setIsOpen(false);
}}>
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
21131 次 |
| 最近记录: |