Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update fails with scrambled DOM result #32

Closed
mindplay-dk opened this issue Jul 16, 2019 · 17 comments
Closed

Update fails with scrambled DOM result #32

mindplay-dk opened this issue Jul 16, 2019 · 17 comments
Labels
bug Something isn't working

Comments

@mindplay-dk
Copy link
Contributor

I created the following small test example:

https://codesandbox.io/s/determined-butterfly-uxuic

At the top of the index.jsx file, you can swap the two import statements between fre and preact to see how this was supposed to work.

With preact:

preact

With fre:

fre

As you can see, the app breaks down as soon as you try to add another counter.

(Is key actually supported? Without support for key-based diffing, it's very hard to make any meaningful use of stateful functional components...)

@yisar
Copy link
Collaborator

yisar commented Jul 16, 2019

@mindplay-dk I'm sorry, now fre's key is not valid for components, and only ordinary element's key is currently supported.

I've got a new idea here recently, and it's likely to come true soon.

Or do you have any suggestions?

@mindplay-dk
Copy link
Contributor Author

Well, missing support for key probably should be tracked in a separate issue.

The main issue with this example is the DOM getting scrambled when main App component updates - that happens even if you remove the key attribute from the example.

@yisar
Copy link
Collaborator

yisar commented Aug 29, 2019

Halo, I've fixed this case now, and now It can get the correct rendering, but the diff result is still not the smallest.
I've been busy in class recently. Please give me more time.

import { h, render, useState } from 'fre'

function App () {
  const [arr, setArr] = useState(1)
  return (
    <div>
      {new Array(arr).fill().map(i => (
        <A val={i} key={i}/>
      ))}
      <button onClick={() => setArr(arr+1)}>+</button>
    </div>
  )
}

function A (props) {
  const [count, setCount] = useState(0)
  return (
    <div>
      {count}
      <button onClick={() => setCount(count + 1)}>+</button>
    </div>
  )
}

render(<App />, document.body)

Or Could we study diff under fiber together?

yisar pushed a commit that referenced this issue Aug 29, 2019
@mindplay-dk
Copy link
Contributor Author

I tried updating my example to 1.5.5, but I can't get the package to load at all now.

For example, if I do this:

import * as fre from "fre";
console.log(fre);

All I see in the console is { default: {} }.

It seems nothing is exported. The module build is maybe broken somehow?

@yisar
Copy link
Collaborator

yisar commented Aug 30, 2019

@mindplay-dk I found some bugs in my diff scheme again. I will write a new diff scheme during the holidays. Thank you for your use case.

@yisar
Copy link
Collaborator

yisar commented Aug 30, 2019

Ah ah! I found a JSX black magic to help solve this problem.
Please wait for my code pushing this weekend~

@yisar
Copy link
Collaborator

yisar commented Aug 31, 2019

Rewrite the diff schema, fix this case, upgrade to the latest version.

@mindplay-dk
Copy link
Contributor Author

The module works again - but now the elements aren't getting ordered correctly:

image

Also, the disabled-attribute on the "Remove" button doesn't seem to update anymore.

You can fork/test my example for yourself here:

https://codesandbox.io/s/determined-butterfly-uxuic

(You should probably think about adding at least a basic test-suite - complex things like these have a tendency to break very easily, even with small changes. It can be very difficult to manually test for every possible thing that could break.)

@yisar
Copy link
Collaborator

yisar commented Sep 2, 2019

@mindplay-dk Agree. I have to admit that diff of the fiber list is really difficult. The main obstacle is the traversal of linked list.

I need more time to study it carefully. No other libraries have similar logic expect React, that makes it difficult for me to emulate.

Please wait for my reply, thanks!

@mindplay-dk
Copy link
Contributor Author

You're brave for even attempting this 💪😁

@yisar yisar added the bug Something isn't working label Sep 2, 2019
@yisar yisar pinned this issue Sep 18, 2019
@yisar
Copy link
Collaborator

yisar commented Sep 23, 2019

@mindplay-dk Hey ~ I'm on vacation now. I've refactor a new version. It looks like it can solve the problem now.

This is not necessarily true, but the current way should be correct!

@yisar yisar closed this as completed in 42a5ab5 Sep 23, 2019
@yisar yisar reopened this Sep 23, 2019
@mindplay-dk
Copy link
Contributor Author

Works better now, components get created/destroyed and maintain state correctly. 👍

There's one problem remaining in my example though: the disabled property on the "Remove" button isn't being updated.

Looks like two things are missing here:

  1. You're mapping props to setAttribute() calls, which only works for HTML attributes, which is not the same as object properties - for example, dom.disabled is a Boolean property, whereas dom.setAttribute("disabled", value) expects a string value; HTML attributes are always strings.

  2. You only set attributes - you need to also be able to remove them.

You can see examples of both here. (Note that this implementation tracks whether a target element is an SVG node or not - something you may need to do later, if you want to support SVG. For reference, see also Preact's implementation here.)

@yisar
Copy link
Collaborator

yisar commented Sep 24, 2019

Ah……you're right. It's my oversight. I'm going to fix it and support svg, too.

@yisar
Copy link
Collaborator

yisar commented Sep 24, 2019

I fixed this and supported SVG…… but the size now reached 2kb!So sad 😢

@mindplay-dk
Copy link
Contributor Author

mindplay-dk commented Sep 24, 2019

2 KB for something like this is extremely good - focus on ensuring the project's integrity (tests!) and worry about optimizing for size later, when it's safe to do so. Refactoring for size at this stage, without tests, is extremely risky.

Do you have a preference for a test-framework? I see you have jest in there, so I might try to help out and get some basic tests going. 🙂

@yisar
Copy link
Collaborator

yisar commented Sep 24, 2019

I really like testing framework T_T. but I'm not very good at it, but I think it's necessary.
Thank you very much !

@mindplay-dk
Copy link
Contributor Author

I've confirmed the fix in 1.6.0 👍

I'm closing this issue, thanks! (Let's continue the discussion about tests elsewhere.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants