我正在尝试制作一个时间跟踪应用程序。我的问题是我试图在包含特定日期值的第一个元素上呈现“日期标头”。我正在使用Cloud Firestore。
我在考虑解决方案,其中我将能够基于日期将检索到的数组拆分为多个块,例如,2020年7月25日=将从那天开始一直进行分组,然后在该块的第一个元素上渲染标题。但是我不知道如何执行。
我将用屏幕截图进行解释。
我现在在哪里:
我要去的地方:
这是我在处理大多数Firestore事件的组件中的代码:
// Main Render
const Times = props => {
// Handling the state
const [hours, setHours] = useState(''); // Hours
const [minutes, setMinutes] = useState(''); // Minutes
const [description, setDescription] = useState(''); // Description
const [entry, setEntry] = useState([]);
const [isStopped, setIsStopped] = useState(true); // Lottie animation state
const [loading, setLoading] = useState(true); // Loading state
const time_entry = useEntries();
// Update all inputs as you type
const handleHoursChange = event => {
setHours(event.target.value);
};
const handleMinutesChange = event => {
setMinutes(event.target.value);
};
const handleDescriptionChange = event => {
setDescription(event.target.value);
};
// Lottie: initial settings
const defaultOptions = {
loop: false,
autoplay: false,
animationData: animationData,
rendererSettings: {
preserveAspectRatio: 'xMidYMid slice'
}
};
// Get entries on app load
useEffect(() => {
fetch('https://jsonplaceholder.typicode.com/posts')
.then(response => response.json())
.then(json => {
setTimeout(() => setLoading(false), 1000);
});
}, []);
// Load all documents from firebase collection on initial app load
function useEntries() {
useEffect(() => {
firebase.db
.collection('time_entries')
.orderBy('createdOn.timestamp', 'desc')
.onSnapshot(snapshot => {
const newEntry = snapshot.docs.map(doc => ({
id: doc.id,
...doc.data()
}));
setEntry(newEntry);
});
}, []);
return entry;
}
// Date variable
var date = new Date();
// Send entry onSubmit
function onSubmit(e) {
e.preventDefault();
// Perform lottie animation
setIsStopped(false);
setTimeout(() => setIsStopped(true), 400);
firebase.db
.collection('time_entries')
.add({
description,
hours,
minutes,
createdOn: {
date: date.toLocaleDateString(),
time: date.toLocaleTimeString(),
timestamp: date.toLocaleString()
}
})
.then(() => {
setDescription('');
setHours('');
setMinutes('');
});
}
return (
<section className="Times">
<div style={{ maxWidth: props.width, width: '100%' }}>
<form className="Form" onSubmit={onSubmit}>
<div className="TimeInput">
<TimeSelect
variant="dropdown"
unit="hours"
value={hours}
onChange={handleHoursChange}
/>
<span>:</span>
<TimeSelect
variant="dropdown"
unit="minutes"
value={minutes}
onChange={handleMinutesChange}
/>
</div>
<input
className="TextInput"
value={description}
placeholder="What have you done?"
onChange={handleDescriptionChange}
/>
<div className="SubmitAnimation">
<Lottie
options={defaultOptions}
height={100}
width={100}
isStopped={isStopped}
speed={1.5}
/>
</div>
<ButtonBase className="Button" type="submit" focusRipple>
<Check color="white" size={24} strokeWidth={3} />
</ButtonBase>
</form>
<span className="ItemsHeader">
<p2>Time entries</p2>
<div className="TimeTotal">
<Clock className="Icon" size={16} strokeWidth="3" />
<p2>
Total: <span>15h 30min</span>
</p2>
</div>
</span>
{time_entry.map(time_entry => (
<>
{loading ? (
<>
<FadeIn>
<Placeholder />
</FadeIn>
</>
) : (
<FadeIn>
<TimeItem
hours={time_entry.hours}
minutes={time_entry.minutes}
description={time_entry.description}
date={time_entry.createdOn.timestamp}
doc_id={time_entry.id}
/>
</FadeIn>
)}
</>
))}
</div>
</section>
);
};
export default Times;
firebase的屏幕截图(以更好地想象我如何构造数据):
您想创建一个将日期映射到该日期的条目列表的集合对象-您可以使用simple来实现reduce
,我将在下面提供它。
const testData = [
{ id: "1", time: '2020-07-24T02:00:00.000Z'},
{ id: "2", time: '2020-07-25T15:00:00.000Z'},
{ id: "3", time: '2020-05-24T12:00:00.000Z'},
{ id: "4", time: '2020-06-24T17:00:00.000Z'},
{ id: "5", time: '2020-07-25T04:00:00.000Z'},
{ id: "6", time: '2020-07-15T19:00:00.000Z'},
{ id: "7", time: '2020-07-15T23:00:00.000Z'},
];
const splitIntoDays = (entries) => entries.reduce((collection, entry) => {
const date = new Date(entry.time).toDateString()
collection[date] = [...(collection[date] || []), entry]
return collection;
}, {})
console.log(splitIntoDays(testData));
然后,您可以在自己的内部使用此方法onSnapshot
来将状态设置为此精简对象。您useEffect
需要位于组件的根目录上,该组件将在挂载后运行一次,获取并订阅Firestore。不要从中返回任何内容,只需设置状态即可。
setEntriesSplitByDate(splitIntoDays(newEntries));
然后,在稍后的render方法中,keys
从该对象中提取(将是日期字符串),在标题(h2
)中显示日期字符串,并创建第二个嵌套映射,该映射映射该块列表中的条目,从而呈现一个Entry
每件。
<section>
{Object.keys(entriesSplitByDate).map(dateKey => (
<div key={dateKey}>
<h2>{dateKey}</h2>
{entriesSplitByDate[dateKey].map(entry => (
<EntryItem entry={entry} />
))}
</div>
))}
</section>
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句