Tresjs / tres

Declarative ThreeJS using Vue Components

Home Page:https://tresjs.org

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

primitive `obj` reactivity broken after nodeOps being a function

alvarosabu opened this issue · comments

Describe the bug

Seems like making nodeOps a function #579 broke primitive obj reactivity since we need to create a new element for primitive

Reproduction

local

Steps to reproduce

No response

System Info

System:
    OS: macOS 14.3.1
    CPU: (8) arm64 Apple M1 Pro
    Memory: 68.70 MB / 16.00 GB
    Shell: 5.9 - /bin/zsh
  Binaries:
    Node: 18.14.1 - ~/.nvm/versions/node/v18.14.1/bin/node
    Yarn: 1.22.19 - /usr/local/bin/yarn
    npm: 9.3.1 - ~/.nvm/versions/node/v18.14.1/bin/npm
  Browsers:
    Brave Browser: 120.1.61.116
    Chrome: 123.0.6312.58
    Firefox: 121.0.1
    Safari: 17.3.1
  npmPackages:
    @tresjs/cientos: 3.6.0 => 3.6.0 
    @tresjs/core: workspace:^ => 4.0.0-next.1 
    @tresjs/leches: 0.15.0-next.3 => 0.15.0-next.3 

Used Package Manager

pnpm

Code of Conduct

Maybe @andretchen0 can you give me a hand with this one? The problem is here

tres/src/core/nodeOps.ts

Lines 197 to 199 in 8efe6e0

const newInstance = nodeOps.createElement('primitive', undefined, undefined, {
object: nextValue,
})
. This features is a key one for v4

I was trying to avoid needing to duplicate the code inside of createElement, but now that nodeOps is a function, this is no longer correct.

Let me know

@alvarosabu

Sure thing. I'll have a look!

Hey @alvarosabu !

Fix

One approach to this would be to define the functions and then collect them into an object to return.

Concretely, right now nodeOps looks like ...

export const nodeOps: () => RendererOptions<TresObject, TresObject | null> = () => {
  let scene: TresScene | null = null

  // NOTE: functions are defined in the return object
  return { createElement(tag, _isSVG, _anchor, props): TresObject | null {
    if (!props) props = {}

    if (!props.args) {
      props.args = []
    }

But if it's like the following, then you can call createElement( ... ) from within any function that's defined after.

export const nodeOps: () => RendererOptions<TresObject, TresObject | null> = () => {
  let scene: TresScene | null = null

  // NOTE: createElement, etc. are still defined within the nodeOps function, so they close over scene
  const createElement(tag, _isSVG, _anchor, props): TresObject | null => { ... }
  
  const patchProp(node, prop, prevValue, nextValue) => { ... 
    ...
    // NOTE: patchProp now closes over createElement, so you can call it like so ...
    const newInstance = createElement('primitive', undefined, undefined, { ...
    ...
  }
  
  // NOTE: assemble the `RendererOptions` object and return it.
  return {
   createElement,
   patchProp,
   ...
  }
}

Question

Would you like me to submit a PR?

Thanks @andretchen0 you are completely right, I just created the PR #602