mitosis icon indicating copy to clipboard operation
mitosis copied to clipboard

BUG: useState hook "set" functions break within onUpdate hook (non-React)

Open CKGrafico opened this issue 3 years ago • 13 comments

Scope

  • [x] This only impacts specific generators/outputs (please list them here): svelte

Describe the bug When using useState in your builder or in my project, angular is not rendering the correct code.

To Reproduce Steps to reproduce the behavior:

  1. Create a useState with get and set.
  2. OnUpdate call to the setter.
  3. Angular will generate this code, where setName does not exist.

A link to a https://mitosis.builder.io/ fiddle containing the bug:

Expected behavior When using a setter should work.

Additional context I've oppened this to talk about angular but I can see the same in all the libraries except with react, is use state only compatible with react??

update: see https://github.com/BuilderIO/mitosis/issues/425#issuecomment-1145644830

CKGrafico avatar Jun 01 '22 10:06 CKGrafico

@CKGrafico ~~Our Fiddle examples are actually using an outdated syntax of useState. Let me quickly update those to better reflect how you'd use useState today!~~

The useState hook example you showed should work for all frameworks! You happen to have uncovered a bug in how we transform state-setting logic within hooks.

samijaber avatar Jun 01 '22 13:06 samijaber

I actually misspoke: The useState hook example you showed should work for all frameworks! You happen to have uncovered a bug in how we transform state-setting logic within hooks.

Here is a look at another useState syntax from examples in our docs, which uses SolidJS-like mutation to alter state: https://github.com/BuilderIO/mitosis/blob/main/docs/components.md#state

This syntax works fine at the moment. Your example would look something like this

Feel free to use this one while we investigate what's causing the issues with the syntax you're currently using.

samijaber avatar Jun 01 '22 13:06 samijaber

This issue only occurs with onUpdate hooks. See this fiddle showing that issue is not present in onMount

samijaber avatar Jun 01 '22 14:06 samijaber

I’m starting to feel like a QA Engineer 👷‍♀️

thanks for all your work and responses to all my questions!

CKGrafico avatar Jun 01 '22 16:06 CKGrafico

updated: https://github.com/BuilderIO/mitosis/issues/442

for svelte the issue is with inline arrow functions with and without {}

working () => https://mitosis.builder.io/?outputTab=svelte&code=import+%7B+useState%2C+onUpdate%2C+onMount+%7D+from+%22%40builder.io%2Fmitosis%22%3B%0A%0Aexport+default+function+MyComponent%28props%29+%7B%0A++const+state+%3D+useState%28%7B%0A++++name%3A+%22Steve%22%0A++%7D%29%3B%0A%0A++onMount%28%28%29+%3D%3E+%7B%0A++++state.name+%3D+%27hola%27%3B%0A++%7D%29%3B%0A%0A++return+%28%0A++++%3Cdiv%3E%0A++++++%3Cinput%0A++++++++css%3D%7B%7B%0A++++++++++color%3A+%22red%22%2C%0A++++++++%7D%7D%0A++++++++value%3D%7Bname%7D%0A++++++++onChange%3D%7B%28event%29+%3D%3E+state.name+%3D+event.target.value+%7D%0A++++++%2F%3E%0A++++++Hello%21+I+can+run+in+React%2C+Vue%2C+Solid%2C+or+Liquid%21%0A++++%3C%2Fdiv%3E%0A++%29%3B%0A%7D

broken with () => {} https://mitosis.builder.io/?outputTab=svelte&code=import+%7B+useState%2C+onMount+%7D+from+%22%40builder.io%2Fmitosis%22%3B%0A%0Aexport+default+function+MyComponent%28props%29+%7B%0A++const+state+%3D+useState%28%7B%0A++++name%3A+%22Steve%22%0A++%7D%29%3B%0A%0A++onMount%28%28%29+%3D%3E+%7B%0A++++state.name+%3D+%27hola%27%0A++%7D%29%0A++%0A++return+%28%0A++++%3Cdiv%3E%0A++++++%3Cinput%0A++++++++css%3D%7B%7B%0A++++++++++color%3A+%22red%22%2C%0A++++++++%7D%7D%0A++++++++value%3D%7Bstate.name%7D%0A++++++++onChange%3D%7B%28event%29+%3D%3E+%7B+state.name+%3D+event.target.value+%7D%7D%0A++++++%2F%3E%0A++++++Hello%0A++++++%7Bstate.name%7D%21+I+can+run+in+React%2C+Vue%2C+Solid%2C+or+Liquid%21%0A++++%3C%2Fdiv%3E%0A++%29%3B%0A%7D

const useBindValue = (json: MitosisComponent, options: ToSvelteOptions) => {
  traverse(json).forEach(function (item) {
    if (isMitosisNode(item)) {
      const { value, onChange } = item.bindings;
      if (value && onChange) {
        if (
          onChange.code.replace(/\s+/g, '') ===
          `${value.code}=event.target.value`
        ) {
          delete item.bindings.value;
          delete item.bindings.onChange;
          item.bindings['bind:value'] = value;
        }
      }
    }
  });
};

https://github.com/BuilderIO/mitosis/blob/main/packages/core/src/generators/svelte.ts#L250...L266

onChange.code.replace(/\s+/g, '') === `${value.code}=event.target.value`

^ this code is outdated we now allow for custom event names and this only works if you don't use the arrow function brackets

PatrickJS avatar Jun 03 '22 06:06 PatrickJS

I made a fix for svelte https://github.com/BuilderIO/mitosis/pull/439/commits/c17d05321abb82fc35cf687cf872c42441e832fd

PatrickJS avatar Jun 03 '22 07:06 PatrickJS

@PatrickJS Not sure why you changed this github issue though. Does #439 fix useState + onUpdate for Angular? I don't see changes in the snapshot there indication so...

Did you mean to create a separate ticket for the svelte bug?

samijaber avatar Jun 03 '22 16:06 samijaber

the angular output looks fine to me

https://stackblitz.com/edit/angular-mxdo5g?file=src%2Fapp%2Fapp.component.html

PatrickJS avatar Jun 03 '22 16:06 PatrickJS

the angular output looks fine to me https://stackblitz.com/edit/angular-mxdo5g?file=src/app/app.component.ts

This link looks unrelated to me? @CKGrafico 's fiddle link in the original post is still broken. I tested it on your branch (pulled locally) and it still incorrectly uses setName

samijaber avatar Jun 03 '22 16:06 samijaber

I'm reverting your changes to this issue. Feel free to create a separate issue for the Svelte problem if that feels like a different scope, or we can keep both here.

samijaber avatar Jun 03 '22 16:06 samijaber

isn't that an issue with useState examples? Mitosis state is

const state = useState({})

or do we support both ways (react-way)

PatrickJS avatar Jun 03 '22 16:06 PatrickJS

@PatrickJS Read this thread in full please.

I explained in https://github.com/BuilderIO/mitosis/issues/425#issuecomment-1143603976 that we support both formats, and that the [foo, setFoo] = useState() format is still supported across all frameworks, and there is a bug in combining that syntax with usage of setFoo within onUpdate

samijaber avatar Jun 03 '22 16:06 samijaber

the helpers to convert all of those all live in the react generator so we would have to move all of those to helpers and apply them to every framework

updateStateSetters, updateStateSettersInCode, getUseStateCode https://github.com/BuilderIO/mitosis/blob/main/packages/core/src/generators/react.ts

PatrickJS avatar Jun 03 '22 16:06 PatrickJS