superfine icon indicating copy to clipboard operation
superfine copied to clipboard

How to unmount?

Open jorgebucaran opened this issue 7 years ago • 20 comments

React has unmountComponentAtNode, preact has render(null, element), etc.

How would that work in Superfine?

patch(null, null, container) // ?

// or

unmount(container) //?

What is it expected from this operation?

jorgebucaran avatar Jul 06 '18 09:07 jorgebucaran

Since the view/components are stateless, my best guess would be maybe calling the lifecycle events for onremove and ondestroy? Assuming we are keeping those going forward.

okwolf avatar Jul 07 '18 05:07 okwolf

@okwolf Sounds good.

@mindplay-dk @zaceno Have you ever had to "unmount" your program?

jorgebucaran avatar Jul 07 '18 08:07 jorgebucaran

Since I handle dynamic widgets through conditional rendering, I'm not sure an unmount is really necessary any more. Using a boolean flag to render or not render a widget makes more sense than directly unmounting it. If you need to do clean up, there's lifecycle events.

rbiggs avatar Jul 07 '18 13:07 rbiggs

Hi @rbiggs would you be able to share some sample code on your solution? I'm having trouble doing such a thing because now we can't render/patch with null or "" for empty state. Thanks.

shirotech avatar Jul 09 '18 03:07 shirotech

@jorgebucaran In hyperapp-nestable I do it (since a nestable component is an app in itself) and like others have suggested, I use ondestroy

zaceno avatar Jul 09 '18 06:07 zaceno

What about supporting both patch(null or lastVNode, null, container)?

jorgebucaran avatar Jul 09 '18 06:07 jorgebucaran

Oh you’re talking about an app unmounting itself! That’s a need I have not yet come across.

zaceno avatar Jul 09 '18 08:07 zaceno

@van-nguyen, here a simple example.

import { h, patch } from 'superfine'

let isLoggedIn = true

function UserGreeting(props) {
  return <h1>Welcome back!</h1>
}

function GuestGreeting(props) {
  return <h1>Please sign up.</h1>
}
function Greeting(props) {
  return props.isLoggedIn ? <UserGreeting /> : <GuestGreeting />
}

function LoginButton(props) {
  return (
    <button class='login' onclick={() => handleLogin()}>
      Login
    </button>
  )
}

function LogoutButton(props) {
  return (
    <button class='logout' onclick={() => handleLogin()}>
      Logout
    </button>
  )
}

function handleLogin() {
  isLoggedIn = !isLoggedIn
  login = patch(login, <LoginControl />, document.body)
}

function LoginControl() {

  return (
    <div class='greeting-jumbotron'>
      <Greeting isLoggedIn={isLoggedIn} />
      {
        isLoggedIn && <LogoutButton />
      }
      {
        !isLoggedIn && <LoginButton />
      }
    </div>
  )
}

let login = patch(null, <LoginControl />, document.body)

Here it is live on Codepen

rbiggs avatar Jul 09 '18 15:07 rbiggs

I like this patch(null, null, container) because I think Superfine is a low-level api for vdom. I don't like adding new function to Superfine. but I like adding umount(container) to Hyperapp.

uchcode avatar Jul 12 '18 02:07 uchcode

@uchcode What do you think is the minimal spec (behavior-wise) for this functionality?

I mean, what does it do other than make your VDOM go away?

jorgebucaran avatar Jul 12 '18 02:07 jorgebucaran

I'm wondering if maybe we could change the order of parameters for patch with the node argument last. That way, for the first render you could just do this:

// instead of let login = patch(null, <LoginControl />, document.body)
let login = patch(<LoginControl />, document.body)

And then later use:

login = patch(<LoginControl />, document.body, login)

rbiggs avatar Jul 12 '18 02:07 rbiggs

@rbiggs Nothing to do with this issue? But yeah, I wondered about that too at some point, but chances are you are using patch to create a HOF like render that encapsulates this logic, where the lastNode is already available, as null/undefined on the first patch and then overwritten with the actual previous node for future patches.

I also find the current signature more straightforward.


Not all renders have to look like that by the way. In theory, we could put together a pure view framework that is essentially a reduce loop.

const loop = (last, next) => patch(last, next, document.body)

and use it like so:

allTheNodesInTheWorld.reduce(loop, null)

See here for a practical application in Superfine tests.

jorgebucaran avatar Jul 12 '18 02:07 jorgebucaran

@jorgebucaran It is enough to go away VDOM becase Superfine already has onremove/ondestroy event.

I need to garbage collection of the user code for Superfine at the time of unmounting.

However, I understand that it is difficult because Superfine does not manage user code.

But I'm glad if it's possible.

uchcode avatar Jul 12 '18 03:07 uchcode

@uchcode I want to add this feature, one way or another, I just would like to discuss what behavior we all want.

jorgebucaran avatar Jul 12 '18 04:07 jorgebucaran

I'm looking forward to seeing this implemented. My preference would be patch(null, null, container) since it goes well with Superfine being a low-level api.

jimfranke avatar Jul 25 '18 07:07 jimfranke

Thanks, for the input @jimfranke. What do you think should happen when you run patch(null, null, container)?

jorgebucaran avatar Jul 25 '18 07:07 jorgebucaran

@jorgebucaran I think the container element that is being passed to the patch function should be returned to it's initial (empty) state. Or am I missing something here?

jimfranke avatar Jul 25 '18 08:07 jimfranke

That means the root element (not the container) should be removed, therefore it should disappear from the page. Sounds reasonable.

jorgebucaran avatar Jul 25 '18 08:07 jorgebucaran

@jorgebucaran Yes, this would be my preferred behaviour :)

jimfranke avatar Jul 25 '18 08:07 jimfranke

Unmounting (calling life-cycle events) would just be patch(lastState, null, container) right?

Describing this as "unmounting" doesn't really make much sense though, as nothing gets "mounted" in the first place - the library is stateless, it isn't mounting a component in the DOM or something, it's just simply "patching", according to the new/old state you provide.

If you provide a null state, it removes the nodes - still just a "patch" by any other name.

Just my two cents.

mindplay-dk avatar Oct 22 '18 06:10 mindplay-dk