Skip to content

Instantly share code, notes, and snippets.

@gregberge
Created June 7, 2019 14:25
Show Gist options
  • Save gregberge/4996ba3eff93d271b3babff86d1c55f0 to your computer and use it in GitHub Desktop.
Save gregberge/4996ba3eff93d271b3babff86d1c55f0 to your computer and use it in GitHub Desktop.
// App.js
import React, { useState, useEffect, useRef } from 'react'
import {
Normalize,
Grid,
Typography,
Row,
Col,
Button,
} from '@smooth-ui/core-sc'
import SearchInput from './components/SearchInput'
import Catch from './components/Catch'
import Card from './components/Card'
import { useDebounce } from './components/Debounce'
import { MovieSearch } from './components/MovieDb'
import { T, useI18n } from './components/I18n'
function useEventListener(target, event, handler) {
const handlerRef = useRef()
useEffect(() => {
handlerRef.current = handler
})
useEffect(() => {
function handleEvent(event) {
handlerRef.current(event)
}
target.addEventListener(event, handleEvent)
return () => target.removeEventListener(event, handleEvent)
}, [event, target])
}
function useActiveKeys() {
const activeKeysRef = useRef([])
useEventListener(document, 'keydown', event => {
activeKeysRef.current = [
...new Set([...activeKeysRef.current, event.keyCode]),
]
})
useEventListener(document, 'keyup', event => {
activeKeysRef.current = activeKeysRef.current.filter(
keyCode => keyCode !== event.keyCode,
)
})
return activeKeysRef
}
const keyCodes = {
alt: 18,
f: 70,
}
function getShortcutKeys(shortcut) {
return shortcut.split('+').map(key => keyCodes[key])
}
function useShortcutEffect(shorcut, effect) {
const activeKeys = useActiveKeys()
useEventListener(document, 'keydown', event => {
const shortcutKeys = getShortcutKeys(shorcut)
if (shortcutKeys.every(keyCode => activeKeys.current.includes(keyCode))) {
effect()
event.preventDefault()
}
})
}
export default function App() {
const [query, setQuery] = useState('Lord of the Rings')
const debouncedQuery = useDebounce(query, 200)
const catchRef = React.useRef()
const { locale, setLocale } = useI18n()
const inputRef = React.useRef()
React.useLayoutEffect(() => {
console.log('effect')
})
React.useEffect(() => {
catchRef.current.retry()
}, [])
React.useEffect(() => {
inputRef.current.focus()
}, [])
useShortcutEffect('alt+f', () => {
inputRef.current.focus()
})
return (
<>
{/* Le composant "Grid" centre dans la page, "py" signifie "padding-top" et "padding-bottom" */}
<Grid py={200}>
{/* Injection de normalize.css pour avoir un rendu consistant sur tous les navigateurs */}
<Normalize />
<Button
type="button"
onClick={() => setLocale(locale => (locale === 'fr' ? 'en' : 'fr'))}
>
<T id={locale} />
</Button>
{/* "Typography" est un composant avec des variantes de titres prêtes à l'emploi */}
<Typography variant="display-1">
<T id="title" />
</Typography>
{/* Le composant "SearchInput" */}
<SearchInput
ref={inputRef}
value={query}
onChange={event => setQuery(event.target.value)}
mb={20}
/>
<Catch ref={catchRef}>
<Row>
<MovieSearch query={debouncedQuery}>
{movies =>
movies &&
movies.map(movie => (
<Col key={movie.id} my={1} xs={12} md={6}>
<Card
style={{
height: 200,
backgroundImage: movie.backdrop_path
? `url(https://image.tmdb.org/t/p/original/${
movie.backdrop_path
})`
: null,
}}
>
<Card.Body>
<Card.Title>{movie.title}</Card.Title>
<Card.Subtitle>
{movie.vote_average} ({movie.vote_count} votes)
</Card.Subtitle>
</Card.Body>
</Card>
</Col>
))
}
</MovieSearch>
</Row>
</Catch>
</Grid>
</>
)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment