preact pubnub twitter firehose
by Kye Hohenberger
HTML
<script src="https://unpkg.com/preact"></script>
<script src="https://cdn.pubnub.com/sdk/javascript/pubnub.4.4.4.min.js"></script>
SCSS
html, body {
background: #EEE;
margin: 0;
font: 16px/1.3 'Helvetica Neue', helvetica, arial, sans-serif;
color: #000;
}
.count {
position: fixed;
right: 0;
top: 0;
padding: 10px;
background: #000;
color: #FFF;
z-index: 100;
}
.item {
position: relative;
box-sizing: border-box;
padding: 10px;
width: 100%;
height: 90px;
background: #FFF;
border-bottom: 1px solid #DDD;
overflow: hidden;
contain: strict;
}
.avatar {
float: left;
margin: 0 10px 0 0;
width: 48px;
height: 48px;
img {
width: 48px;
height: 48px;
border-radius: 3px;
}
}
.author-name {
color: #555;
text-decoration: none;
font-weight: bold;
}
.author-screenname {
color: #AAA;
margin-left: 1em;
text-decoration: none;
font-size: 80%;
}
.text {
margin: 0;
padding: 0;
overflow: hidden;
}
Babel + JSX
const { h, Component, render } = preact; /** @jsx h */
/** Demo: Stream twitter firehose into
* a naive VDOM list with shouldComponentUpdate.
*/
class Demo extends Component {
state = {
messages: []
};
handleMessage = msg => {
// we'll mutate in-place to save some copy ops
// TIP: you can store VDOM in state!
// Avoids constantly re-mapping data -> VDOM in render.
this.state.messages.push(
<Message id={msg.message.id_str} message={msg.message} />
);
// just trigger a state update
this.setState();
};
componentDidMount() {
let stream = new PubNub({
subscribeKey: 'sub-c-78806dd4-42a6-11e4-aed8-02ee2ddab7fe'
});
stream.addListener({
message: this.handleMessage
});
stream.subscribe({
channels: ['pubnub-twitter']
});
}
render({ }, { messages }) {
return (
<div class="list">
<span class="count">{messages.length} tweets ({messages.length*9} elements)</span>
{messages}
</div>
);
}
}
class Message extends Component {
shouldComponentUpdate(nextProps) {
return nextProps.id!==this.props.id;
}
render({ message }) {
let profileUrl = 'https://twitter.com/'+message.user.screen_name;
return (
<div class="item">
<a class="avatar" href={profileUrl} target="_blank">
<img src={message.user.profile_image_url_https} />
</a>
<a class="author-name" href={profileUrl} target="_blank">
{message.user.name}
</a>
<a class="author-screenname" href={profileUrl} target="_blank">
@{message.user.screen_name}
</a>
<p class="text">{message.text}</p>
</div>
);
}
}
render(<Demo />, document.body);