Files
koodiklinikka.fi/components/Feed.tsx
Olavi Haapala ca5b251c7c Fix some performance issues
* Remove render blocking stripe JS that seems unnecessary
* Use native lazy loading of images
  - Truly a progressive enhancement, only affects browsers that support it
  - Causes a warning: [Intervention] An <img> element was lazyloaded with loading=lazy, but had no dimensions specified. Specifying dimensions improves performance. See https://crbug.com/954323, which can not be easily fixed
* Render content first, hydrate after that
2020-09-22 21:46:25 +03:00

82 lines
2.2 KiB
TypeScript

import flatMap from "lodash/flatMap";
import sortBy from "lodash/sortBy";
import React from "react";
import request from "axios";
import api from "./api";
import transformers from "./feed-transformers";
import ReactTimeAgo from "react-time-ago";
import JavascriptTimeAgo from "javascript-time-ago";
import timeagoFi from "javascript-time-ago/locale/fi";
// TODO: Add type definitions for javascript-time-ago
(JavascriptTimeAgo as any).locale(timeagoFi);
export default class Feed extends React.Component {
state = {
messages: [],
};
componentDidMount() {
this.updateFeed();
}
async updateFeed() {
const res = await request.get(api("feeds"));
const messages = sortBy(
flatMap(res.data, (messages, type) => transformers[type](messages)),
"timestamp"
);
messages.reverse(); // In-place
this.setState({
messages: messages.slice(0, 40),
});
}
render() {
const messages = this.state.messages.map((message, i) => {
let image = <img src={message.image} alt="" loading="lazy" />;
if (message.imageLink) {
image = (
<a
target="_blank"
href={message.imageLink}
rel="noopener noreferrer"
tabIndex={-1}
>
{image}
</a>
);
}
return (
<div className="message" key={i}>
<div className="message__image" aria-hidden="true">
{image}
</div>
<div className="message__content">
<div className="message__user">
<a href={message.userLink}>{message.user}</a>
</div>
<div
className="message__body"
dangerouslySetInnerHTML={{ __html: message.body }}
/>
<div className="message__icon">
<i className={`fa fa-${message.type}`} aria-hidden="true" />
</div>
<div className="message__details">
<span className="message__timestamp">
<ReactTimeAgo date={message.timestamp} locale="fi" />
</span>
<span className="message__meta">{message.meta}</span>
</div>
</div>
</div>
);
});
return <div className="feed">{messages}</div>;
}
}