Skip to content

Instantly share code, notes, and snippets.

@grampelberg
Last active March 21, 2020 01:27
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save grampelberg/275d0a97f020962efa9f81adb909802d to your computer and use it in GitHub Desktop.
Save grampelberg/275d0a97f020962efa9f81adb909802d to your computer and use it in GitHub Desktop.
import React, { useState, useEffect, useRef } from 'react';
import fetch from 'fetch-hoc';
import classNames from 'classnames';
import { useHotkeys } from 'react-hotkeys-hook';
const scrollOpts = { behavior: "smooth", block: "nearest" };
const Row = props => {
const {data, selected} = props;
const [visible, setVisible] = useState(true);
const ref = useRef(null);
let className = classNames({
"list-group-item": true,
"active": selected,
});
let changeVisibility = entries =>
entries.forEach(({isIntersecting}) => setVisible(isIntersecting));
useEffect(() => { if (!visible && selected && ref) { ref.current.scrollIntoView(scrollOpts) } }, [selected]);
useEffect(() => {
(new IntersectionObserver(changeVisibility, { root: null, threshold: 1 })).observe(ref.current);
}, [ref])
return (
<li ref={ref} className={className}>{data}</li>
)
}
const App = props => {
let {error, loading, data} = props;
const [selected, setSelected] = useState(0);
useHotkeys('j', () => (selected >= data.length) || setSelected(selected+1), [selected, data]);
useHotkeys('h', () => (selected === 0) || setSelected(selected-1), [selected, data]);
if (error || loading) { return <div />; }
return (
<div className="container pt-3">
<ul className="list-group">
{data.map((r, i) => <Row data={r} key={i} selected={i === selected} />)}
</ul>
</div>
);
}
export default fetch('https://baconipsum.com/api/?type=meat-and-filler?paras=50')(App);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment