hooks-component
Addon used to experiment with @glimmer/component
style APIs in Ember apps via
existing public APIs.
Installation
ember install hooks-component
This addon provide 2 DIFFERENT API's
- React - Way hooks implementation (always call component function on rerender).
- Ember - way hooks implementation (call component function on first render only).
Usage in React-Way
The hooks-component
API supports public React HooksAPI
Builtin hooks
useEffect
-> just like in React APIuseState
-> just like in React APIuseLayoutEffect
-> just like in React API
getService
->getService(serviceName)
-> service lookup hookgetController
->getController(serviceName)
-> controller lookup hookgetRoute
->getRoute(routeName)
-> route lookup hookgetStore
-> store service lookupgetOwner
->getOwner()
-> equalsgetOwner(this)
in Ember.
Example
; { const speakers = ; const current updateCurrent = ; ; const next = { let nextSpeaker = current + 1; ; } return currentlySpeaking: speakerscurrent moreSpeakers: speakerslength - 1 > current current next speakers } ConferenceSpeakersReact;
{{!-- app/templates/components/conference-speakers-react.hbs --}} <div> <p>Speaking: {{currentlySpeaking}}</p> <ul> {{#each speakers key="@index" as |speaker|}} <li>{{speaker}}</li> {{/each}} </ul> {{#if moreSpeakers}} <button onclick={{action next this.current}}>Next</button> {{else}} <p>All finished!</p> {{/if}}</div>
How to create custom hooks?
getContextId
->getContextId()
-> get current instance context id (same between rerenders)getRerender
-> return binded to current instanceupdate
functionaddBeforeCallTask
-> execute some callback before componentupdate
addBeforeDestroyTask
-> execute some callback before any componentdestroy
// utils/custom-hook.js ; const DUMMY_STORE = {};var CALL_COUNTER = 0; ; ; { const uid = ; // current component instance ID const hookCallId = CALL_COUNTER; // how many times hook called during rendering if !uid in DUMMY_STORE DUMMY_STOREuid = {}; // init store for component instance; if !hookCallId in DUMMY_STOREuid // init store for exact call number inside component isntance; DUMMY_STOREuidhookCallId = componentStoreDefaultValue; // get current instance + callNumber state let state = DUMMY_STOREuidhookCallId; // get rerender function (must be inside hook) let rerender = ; // increment hook call counter CALL_COUNTER++; // return current state for exact component and callNumber and update state function return state { Object; // rerender will invoke component rerender ; }}
;; { const state patchState = ; const fish patchFish = ; const keys = state; const salmon = fish; const next = { } const addSalmon = { } return keys next salmon } ConferenceSpeakersReact;
Usage in Ember-Way
The hooks-component
API supports part of React hooks API, including:
updateContext - just like setProperties;
useEffect - do some calculation after dependent keys changed
extract - just like getWithDefault for component arguments
useEffect
- inside component function
context support: function, tracked property paths in array-like style ['foo.length', 'foo', 'foo.firstObject']
;
All effects called during first render, on rerender effects called only if "tracked" property changed.
Example
// app/components/conference-speakers.js (.ts would also work); { const updateContext useEffect extract = this; ; const next = { current++; ; } return ;} ConferenceSpeakers;
{{!-- app/templates/components/conference-speakers.hbs --}} <div> <p>Speaking: {{currentlySpeaking}}</p> <ul> {{#each speakers key="@index" as |speaker|}} <li>{{speaker}}</li> {{/each}} </ul> {{#if moreSpeakers}} <button onclick={{action next this.current}}>Next</button> {{else}} <p>All finished!</p> {{/if}}</div>
useEffect API
;;;;
How it's working?
Current hookedComponents implementation logic:
- We run
component function
only once, in component creation time. component function
accept named params (args
) as first argument, and returncontext object
.updateContext
method invoke existing effects and then, dosetProperties(currentContext, updatedProps)
.- if component
args
updated, it invokesupdateContext
method with updatedargs
. useEffect
method adds "afterupdateContext
and beforesetProperties
callbacks withupdatedProps
object as argument";- if
useEffect
call return function, it will be callded before this effect call next time. updateContext
insideuseEffect
don't reinvoke effects, just patchingupdatedProps
with new data.
Contributing
Installation
git clone <repository-url>
cd hooks-component
yarn install
Linting
yarn lint:js
yarn lint:js --fix
Running tests
ember test
– Runs the test suite on the current Ember versionember test --server
– Runs the test suite in "watch mode"ember try:each
– Runs the test suite against multiple Ember versions
Running the dummy application
ember serve
- Visit the dummy application at http://localhost:4200.
For more information on using ember-cli, visit https://ember-cli.com/.
License
This project is licensed under the MIT License.