Skip to content

Instantly share code, notes, and snippets.

@suhaotian
Forked from ryanflorence/Articles.js
Last active December 23, 2016 02:33
Show Gist options
  • Select an option

  • Save suhaotian/399f69264df48f5aa807b672629d4ce5 to your computer and use it in GitHub Desktop.

Select an option

Save suhaotian/399f69264df48f5aa807b672629d4ce5 to your computer and use it in GitHub Desktop.
import React from 'react'
import Router from 'react-router/BrowserRouter'
import Match from 'react-router/Match'
import Link from 'react-router/Link'
import Redirect from 'react-router/Redirect'
// function elementInViewport(el) {
// var top = el.offsetTop
// var left = el.offsetLeft
// var width = el.offsetWidth
// var height = el.offsetHeight
// while(el.offsetParent) {
// el = el.offsetParent
// top += el.offsetTop
// left += el.offsetLeft
// }
// return (
// top < (window.pageYOffset + window.innerHeight) &&
// left < (window.pageXOffset + window.innerWidth) &&
// (top + height) > window.pageYOffset &&
// (left + width) > window.pageXOffset
// )
// }
function elementInViewport(element) {
let bounds = element.getBoundingClientRect();
return bounds.bottom > 0
&& bounds.right > 0
&& window.innerWidth - bounds.left > 0
&& window.innerHeight - bounds.top > 0;
}
class InView extends React.Component {
componentDidMount() {
this.checkVisibility()
window.addEventListener('scroll', this.checkVisibility)
}
componentWillUnmount() {
window.removeEventListener('scroll', this.checkVisibility)
}
checkVisibility = () => {
if (elementInViewport(this.node)) {
this.props.onVisible()
}
}
render() {
return <div ref={n => this.node = n}>&nbsp;</div>
}
}
class Articles extends React.Component {
state = {
gists: [],
fetchedGists: []
}
componentDidMount() {
fetch('https://api.github.com/gists/public').then(res => res.json()).then(
(gists) => {
this.setState({ gists })
this.fetchGist(gists[0].id)
}
)
}
fetchGist(id) {
fetch(`https://api.github.com/gists/${id}`).then(res => res.json()).then(
(gist) => {
this.setState({
fetching: false,
fetchedGists: this.state.fetchedGists.concat([ gist ])
})
}
)
}
fetchNextGist = () => {
this.setState({ fetching: true })
const { fetchedGists, gists } = this.state
const lastFetched = fetchedGists[fetchedGists.length - 1]
const index = gists.indexOf(gists.find(gist => gist.id === lastFetched.id))
this.fetchGist(gists[index+1].id)
}
render() {
const { gists, fetchedGists, fetching } = this.state
return (
<Router>
<div>
{fetchedGists.map((gist, index) => (
<article style={{ margin: '20px', border: '1px solid', padding: '20px' }}>
<h1>{gist.description || 'No Description'}</h1>
{Object.keys(gist.files).map(fileName => (
<div>
<h2>{fileName}</h2>
<pre>{gist.files[fileName].content}</pre>
</div>
))}
{index === fetchedGists.length - 1 && (
<Redirect to={`/gists/${gist.id}`} replace={true}/>
)}
</article>
))}
{!fetching && fetchedGists.length && (gists.length > fetchedGists.length) && (
<InView onVisible={this.fetchNextGist}/>
)}
</div>
</Router>
)
}
}
export default Articles
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment