Skip to content

Instantly share code, notes, and snippets.

@akameco
Created July 28, 2017 17:17
Show Gist options
  • Save akameco/22f1ad067ecb349c606e5f8c0003eb61 to your computer and use it in GitHub Desktop.
Save akameco/22f1ad067ecb349c606e5f8c0003eb61 to your computer and use it in GitHub Desktop.
Typing Demo
// @flow
import React, { Component } from 'react'
import EventListener from 'react-event-listener'
import lodash from 'lodash'
import catNames from './catNames'
import './App.css'
type TargetType = string
const Target = ({ word, active }: { word: TargetType, active: boolean }) =>
<span className={active ? 'Target-is-active' : 'Target'}>
{word}
</span>
const Title = () => <h2>Typing Game</h2>
const List = ({ list, activeId }: { list: TargetType[], activeId: number }) =>
<div className="List">
{list.map((v, i) => <Target key={v} word={v} active={activeId === i} />)}
</div>
const Button = ({
onClick,
children,
}: {
onClick: () => void,
children?: React.Element<*>,
}) =>
<button onClick={onClick} className="Button">
{children}
</button>
const ClearButton = ({ onClick }: { onClick: () => void }) =>
<Button onClick={onClick}>CLEAR</Button>
const ShowWord = ({ word }: { word: string }) =>
<h1>
{word}
</h1>
const Timer = ({
count,
isStarting,
}: {
count: number,
isStarting: boolean,
}) => {
return (
<h3>
Timer:{' '}
<span
className={!isStarting && count !== 0 ? 'Timer-is-finish' : 'Timer'}
>
{count}
</span>
s
</h3>
)
}
type AppState = {
currentWord: string,
targetList: TargetType[],
currentChar: string,
activeId: number,
count: number,
isStarting: boolean,
}
const createList = (): string[] => lodash.take(lodash.shuffle(catNames), 15)
class App extends Component {
state: AppState = {
currentWord: '',
targetList: createList(),
activeId: 0,
currentChar: '',
count: 0,
isStarting: false,
}
timer: number
startTimer = () => {
this.setState({ isStarting: true, count: 0 })
this.timer = setInterval(() => {
this.setState({ count: this.state.count + 1 })
}, 1000)
}
componentWillMount() {
if (this.timer) {
clearInterval(this.timer)
}
}
componentDidUpdate() {
const { targetList, activeId } = this.state
if (activeId >= targetList.length) {
this.finish()
}
}
shuffleList = () => {
this.setState({ targetList: createList() })
}
finish = () => {
clearInterval(this.timer)
this.setState({
activeId: 0,
currentWord: '',
currentChar: '',
isStarting: false,
})
}
handleClear = () => {
clearInterval(this.timer)
this.setState({
activeId: 0,
currentWord: '',
currentChar: '',
isStarting: false,
count: 0,
})
}
clearInput = () => {
this.setState({ currentWord: '' })
}
handleKeyUp = (e: any) => {
e.preventDefault()
const { key } = e
const { targetList, activeId, currentWord, isStarting } = this.state
if (!isStarting) {
this.startTimer()
}
const currentTarget = targetList[activeId]
if (!/^[A-Za-z0-9]$/.test(key)) {
return
}
this.setState({ currentChar: key })
if (currentTarget[currentWord.length] !== key) {
return
}
this.setState({ currentWord: this.state.currentWord + key }, () => {
if (currentTarget === this.state.currentWord) {
this.setState({ activeId: activeId + 1 })
this.clearInput()
}
})
}
render() {
const { targetList, currentWord, activeId, currentChar, count } = this.state
return (
<div className="App">
<EventListener onKeyUp={this.handleKeyUp} target="window" />
<Title />
<Timer count={count} isStarting={this.state.isStarting} />
<List list={targetList} activeId={activeId} />
<ShowWord word={currentWord} />
<h2>
{currentChar}
</h2>
<Button onClick={this.handleClear}>CLEAR</Button>
<Button onClick={this.shuffleList}>SHUFFLE</Button>
</div>
)
}
}
export default App
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment