Ways to avoid forgetting to call this.refresh() #104
Replies: 4 comments 9 replies
-
I’m currently writing a blogpost talking about why I think an explicit refresh is better. In the meantime, you might want to read the thoughts various people have here: #37 I’m curious about the concrete workflow you had when you made the bug, what you were doing, how hard it was to discover the cause of the bug, and whether you have made the bug fewer times since getting used to the cranky way. My theory is that explicit calls to this.refresh are good. They’re good for debuggability, and when they’re missing it’s immediately obvious, and it’s actually valuable feedback in the course of development because it teaches you “hey” this component isn’t rerendered by the parent and requires a refresh. But you can always consider explicit refreshes a low-level interface and build stateful things on top of the Crank context which calls refresh automatically, or you can use async generator components which continuously have values pulled. I’m collecting my thoughts about this but will write more here and in #37 when I can. |
Beta Was this translation helpful? Give feedback.
-
OK, just to stimulate the conversation (and probably annoy Brian... ;-)): here's an example of using a Proxy to wrap a UI data object to automate
...
This works. A couple things to note:
As long as the UI components only reference data values via the proxy, which could be enforced using conventional Javascript scoping rules, All of that said, I'm not yet convinced whether this is a generally useful idiom or not; Brian has been "cranky" a lot longer than I have and has thought about this a lot more, so I'm not ready to dismiss his admonition that explicitly calling |
Beta Was this translation helpful? Give feedback.
-
@jonrsawyer Not really sure whether this could be interesting for you ... anyway, here's a little demo using a library called "observable-slim" (version 0.1.5) |
Beta Was this translation helpful? Give feedback.
-
@brainkim Frankly (sorry for being annoying again), sooner or later you really have to face (and answer) the question whether writing "Vue3/Hooks"-like helper functions in userland and using them over and over again with (a future version of) Crank is a proper way to implement Crank components or whether this is not cranky at all and should never be done. // Important: All functions used in this example are written completely in userland,
// they are NOT part of the Crank core.
// In the current Crank version, it's not possible to implement most of these functions,
// but who knows, this may change in future.
// The following is obviously highly inspired by Vue3 and React hooks
// (but completely non-magical).
function* Counter() {
const
props = propsWithDefaults(this, { label: 'Counter', initialCount: 0 }),
state = reactive(this, { count: props.initialCount )),
onIncrement = () => { ++state.count }
onMounted(this, () => {
console.log('Component has been mounted')
})
onBeforeUnmount(this, () => {
console.log('Component will be unmounted')
})
onUpdated(this, () => {
console.log(`Value of "${props.label}": ${state.count}`)
}, () => [state.count]) // this is similar to useEffect in React
while (true) {
yield <button onclick={onIncrement}>{props.label} {state.count}</button>
}
}) |
Beta Was this translation helpful? Give feedback.
-
As I experiment with my Material Design components using Crank, I have repeatedly misled myself into thinking I had some sort of component definition problem, when in fact all I'd done is forgotten to call
this.refresh()
. Oops.Any ideas on idioms to use to avoid this potentially common pitfall? Other than "be smarter"? :-)
In some ways it seems kinda like a cross-cutting concern that AOP may lend itself to, but that may be overkill.
I was thinking about the possibility of all "
onevent
" calls from the UI components could implicitly callthis.refresh()
after calling application code, but that may be a mistake for a variety of reasons: some UI events may not need to trigger a refresh, while other non-UI events will need to, and it may be even less obvious to application programmers why it is needed in some cases rather than others.Conceptually, I'd like to "draw a bubble" around all application callbacks, and have a conceptual equivalent of
try ... finally
causethis.refresh()
to be called (once!) upon completion of the callback(s). Ideally, a callback could "opt out" of the need for a refresh as an optimization somehow, but a default behavior of refreshing (instead of the current default of not refreshing when you don't callthis.refresh()
) seems to be a "safer" behavioral pattern. A concrete mechanism for this does not come to mind, however.Beta Was this translation helpful? Give feedback.
All reactions