CurtisHumphrey / react-keyboard-shortcuts

A declarative library for handling hotkeys based on explicit priority in React applications
MIT License
25 stars 6 forks source link

Functional components and react-keyboard-shortcuts #5

Open asos-albinotonnina opened 5 years ago

asos-albinotonnina commented 5 years ago

Hi, thank you for this library. Best I found! I have a question, does/will react-keyboard-shortcuts work with functional components?

edit: Because of refs I guess not at the moment. Maybe with Hooks at some point I guess?

CurtisHumphrey commented 5 years ago

I think it could be rewritten to include a non-HOC version that would not need a ref.

rajatgalav commented 7 months ago
const hotkey_get_handler = (hotkey) => (e, combo) => {
    const handlers = global_hotkeys[hotkey]
    let propagate = true
    _.forEach(handlers, ({ handler }) => {
        if (!propagate) return
        propagate = handler(e, combo)
    })
    return propagate
}

const load_hotkeys = (handlers) => {
    _.forEach(handlers, (response, hotkey) => {
        if (global_hotkeys[hotkey] == null) {
            global_hotkeys[hotkey] = [response]
            Mousetrap.bind(hotkey, hotkey_get_handler(hotkey))
        } else {
            global_hotkeys[hotkey].push(response)
            global_hotkeys[hotkey] = _.sortBy(global_hotkeys[hotkey], 'priority').reverse()
        }
    })
}
const unload_hotkeys = (handlers) => {
    _.forEach(handlers, (response, hotkey) => {
        _.remove(global_hotkeys[hotkey], response)
        if (global_hotkeys[hotkey].length === 0) {
            global_hotkeys[hotkey] = null
            Mousetrap.unbind(hotkey)
        }
    })
}

export function useHotKeys(hot_keys, ComponentName) {

    useEffect(() => {
        if (!ComponentName) {
            console.warn(`Pass Component name as seconday argument`)
        } else {
            const handlers = hot_keys
            if (handlers === null) {
                console.warn(`Component: ${ComponentName} did not provide hotkey handlers`)
                return
            }
            load_hotkeys(handlers)
        }

        return () => {
            const handlers = hot_keys
            if (handlers == null) return
            unload_hotkeys(handlers)
        };
    });

}

I created a custom hook useHotKeys(), which accepts hot_keys as variable and component name where it is being used. And then it started working for functional components as well.