Giter VIP home page Giter VIP logo

Comments (14)

mcjazzyfunky avatar mcjazzyfunky commented on May 28, 2024

@Zolmeister
May I ask what output the following demo should have according your proposal?
https://codesandbox.io/s/intelligent-moser-c4cjt

from dyo.

Zolmeister avatar Zolmeister commented on May 28, 2024

@mcjazzyfunky Because yield now only represents control-flow, the output would be:

ignored-1
ABC
ignored-2
ignored-3

from dyo.

thysultan avatar thysultan commented on May 28, 2024

@Zolmeister What's the difference new Set(['A', 'B', 'C']) and the others? They both produce sync iterators. Why treat them differently?

from dyo.

Zolmeister avatar Zolmeister commented on May 28, 2024

Oh, yes. My mistake. It would not have ABC (it would be undefined)

ignored-1
ignored-2
ignored-3

from dyo.

mcjazzyfunky avatar mcjazzyfunky commented on May 28, 2024

Thanks for the responses.
Actually I think new Set(...) and function* () {... } should really be treated differently because they are indeed quite different. A set is an iterable (I do not know whether that's the correct ES201x term - but I think you know what I mean) as it has a property someSet[Symbol.iterator] while generator functions do not have such a property (only the return value of a generator function, the iterator, has a [Symbol.iterator] property)

So I think there are good reasons that the result of my demo should indeed be:

ignored-1
ABC
ignored-2
ignored-3

Otherwise the whole support for iterables (except for arrays) in Dyo would be killed.
Using collections/iterables other than arrays would require an explicit iterable to array conversion (using Array.from(...) or whatever).

For example something like the following would not be supported out of the box any longer:
https://codesandbox.io/s/purple-sound-v737x
(in this particular case you would have to convert the lazy sequence to an array explicitly before using it as a child node)

from dyo.

thysultan avatar thysultan commented on May 28, 2024

@Zolmeister In your example:

function* Component() {
  a = yield* useHook()
  return h('div', a) // <div>xxx</div>
} 

You wouldn't need async generator component to archive this, normal async components work fine.

async function Component() {
  const a = await useHook()
  return h('div', {}, a)
} 

or raw promises

function Component() {
  return h('div', {}, useHook())
} 

Async generators allow you to render multiple states:

async function* Component() {
  yield 'Loading...'
  const a = await useHook()
  yield h('div', {}, a)
} 

Which would first render 'Loading...' immediately, then after the useHook has resolved render the div, async generators are uniquely unlike normal async components or normal sync generators.

from dyo.

Zolmeister avatar Zolmeister commented on May 28, 2024

@thysultan Unfortunantely due to the mechanics of hooks, normal async components are crippled (ref #111).

e.g.

async function* Component() {
  yield 'Loading...'
  const a = await useHook()
  // TypeError: Cannot read property 'owner' of null
  const b = await useHook()
  yield h('div', {}, a, b)
} 

Therefore you will almost always want to use the generator style when handling inline-promises.

@mcjazzyfunky I can get behind that. Function components that return generators should be treated differently than generator components.

from dyo.

thysultan avatar thysultan commented on May 28, 2024

Why are the hooks interlaced like that instead of:

async function* Component() {
  const a = useHook()
  const b = useHook()
  yield 'Loading...'
  yield h('div', {}, await a, await b)
} 

from dyo.

Zolmeister avatar Zolmeister commented on May 28, 2024

@thysultan If the hook is async, you can only have one (regardless of interlacing). Some of my hooks are async.

async function* Component() {
  const a = await useHook()
  // TypeError: Cannot read property 'owner' of null
  const b = await useHook2(a)
  yield 'Loading...'
  yield h('div', {}, a, b)
} 

Edit: I see, you await at the end. Imaging the value from one hook needs to be passed to another.

from dyo.

thysultan avatar thysultan commented on May 28, 2024

@Zolmeister I still don't understand, when you use hooks like that you are going against the call order rule of hooks. It is the equivalent of using hooks in a for-loop?

What exactly are you trying to do with the useHook hook?

from dyo.

mcjazzyfunky avatar mcjazzyfunky commented on May 28, 2024

@thysultan
This may be quite an unpleasant question but are you really sure that these "async generator function components" and "promises as elements" features are actually good ideas?
Are there really non-trivial "async generator function components" that behave in a way someone would like? For example when the parent component will be updated but the changes are actually not relevant for the inner async generator function component then the promises inside of the async generator function will nonetheless start to be resolved again.

The following three demos for example do not behave like as I would expect or as I would like:
(1) https://codesandbox.io/s/flamboyant-wescoff-69ri3
(2) https://codesandbox.io/s/bold-rubin-x63s8
(3) https://codesandbox.io/s/romantic-snyder-esuvo

This demo shows a behavior as I would expect:
(4) https://codesandbox.io/s/silly-snowflake-tmrhx

from dyo.

Zolmeister avatar Zolmeister commented on May 28, 2024

@thysultan that's a good point, call-order might break subtly. e.g. getting this to work might be tricky:

X = ->
  useState()
  yield Promise.delay(Math.random() * 100)
  useState()

h 'div', X, X, X

My initial purpose for this feature was to allow hooks which are 'sync' server-side but 'async' client-side. e.g.

useStream = (fn) ->
  return if window?
    useResource(fn)
  else
    useMemo fn, []
X = ->
  user = yield useStream(-> fetch '/user')
  [counter] = useState(0)

However, after some consideration (especially given the comments by @mcjazzyfunky #113 (comment)) I think this is not an efficient approach. I'm closing #114, however I still think this feature is interesting and worth considering.

from dyo.

thysultan avatar thysultan commented on May 28, 2024

@mcjazzyfunky I agree some of the demo's present unexpected behaviour.

'sync' server-side but 'async' client-side

@Zolmeister async works just as well server-side.

useResource can be considered a sync hook since it uses suspense/caching + throwing a promise, so it acts like a sync hook, meaning your example wouldn't need async/yield, unless i'm missing something?

X = ->
  user = useStream(-> fetch '/user')
  [counter] = useState(0)

We could relegate async/promise values to act like the useResource hook that works with Suspense.

from dyo.

Zolmeister avatar Zolmeister commented on May 28, 2024

@thysultan excellent point. I forgot we actually have async hooks via Suspense (a bit leaky, but good enough).

The call-order issue #113 (comment) I think makes this proposal a non-starter. I'm going to close this issue, thanks everyone for the feedback.

from dyo.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.