This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| function useThrottle( fun, timeout, changes = [] ){ | |
| // Create the mutable local ref to store timer. | |
| const timer = useRef( null ); | |
| function cancel(){ | |
| if( timer.current ){ | |
| clearTimeout( timer.current ); | |
| timer.current = null; | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| function useIO( fun, condition = [] ) { | |
| // Counter of open I/O requests. If it's 0, I/O is completed. | |
| // Counter is needed to handle the situation when the next request | |
| // is issued before the previous one was completed. | |
| const $isReady = useSafeLink( null ); | |
| useEffect(()=>{ | |
| // function in set instead of value to avoid race conditions with counter increment. | |
| $isReady.set( x => ( x || 0 ) + 1 ); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| const UsersList = ({ filter, $selected }) => { | |
| // $users can be modified by async function after the component is unmounted. | |
| // We have to do something to prevent an exception. Let's do it in this custom hook. | |
| const $users = useSafeLink([]); | |
| // It's useful to know if there's an I/O peding. Another custom hook. | |
| const ioComplete = useIO( async () => { | |
| // This thing can happen after unmount. | |
| $users.set( await fetchUsers( filter ) ); | |
| }, [ filter ]); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| export function useIsMountedRef(){ | |
| // We need something similar to the plain mutable class member. | |
| const isMounted = useRef( true ); | |
| // And, we need something similar to componentWillUnmount. | |
| useEffect( () => { | |
| // Whatever we return is a cleanup effect. | |
| return () => { // <- componentWillUnmount | |
| isMounted.current = false | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| export function useSafeLink( initialState ){ | |
| const $value = useLink( initialState ), | |
| isMounted = useIsMountedRef(); | |
| const { set } = $value; | |
| $value.set = x => isMounted.current && set( x ); | |
| return $value; | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // npm install valuelink linked-controls --save-dev | |
| // That's what you need to start. | |
| import { useLink } from 'valuelink' | |
| // Hooks used in DelayedInput, and the DelayedInput himself. | |
| import { useBoundLink } from 'valuelink' | |
| import { useThrottle, DelayedInput } from 'linked-controls' | |
| // Hooks used in UsersList |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| export const EditUser = ({ selected, setSelected, close }) => { | |
| // Create the `filter` local state. | |
| const [ filter, setFilter ] = useState(''); | |
| return ( | |
| <div> | |
| <DelayedInput autoFocus | |
| value={ filter } | |
| onChange={ e => setFilter( e.target.value ) } | |
| placeholder="Start typing..." |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| const PickUser = ({ selected, setSelected }) => { | |
| // Declare the local component's state. | |
| const [ editing, setEditing ] = useState( false ); | |
| return ( | |
| <div> | |
| { editing ? | |
| <EditUser selected={selected} setSelected={setSelected} | |
| close={() => setEditing( false )}/> | |
| : |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| class Statement { | |
| constructor( state ){ | |
| this.state = state || []; | |
| } | |
| toString(){ | |
| return this.state | |
| .map( part => part.toString() ) | |
| .join( '\n' ); | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| (()=>{ | |
| const DEPTH = 3; | |
| function learn( word ){ | |
| addStats( '^', word[ 0 ] ); | |
| DEPTH > 2 && addStats( word[ 0 ], word[ 1 ] ); | |
| for( let i = 2; i < DEPTH - 1; i++ ){ | |
| addStats( word.substr( 0, i ), word[i] ); | |
| } |