question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Suggestion for imperative update api

See original GitHub issue

I’m finding this to be a very common pattern I’m using to avoid having react-three-fiber recreate new geometry for objects I need to regularly update. I’m wondering if there’s a nicer api for this.

Let’s say I’m creating a dynamic cube. I regularly do the following:

  • I will create store with its dimensions
  • create geometry and mesh instance, cached in the store
  • have a memoised / reactive function that updates the geometry / mesh based off the cube dimensions
  • apply the updated mesh to the primitive tag
class CubeStore {
    @observable x = 0
    @observable y = 0
    @observable z = 0

    constructor(x,y,z) {
        this.x = x
        this.y = y
        this.z = z
        this._geometry = getCubeGeometry(x,y,z)
    }

    @computed get geometry() {
         const geometry = this._geometry
         geometry.addAttribute('position', getCubeVertices(this.x, this.y, this.z))
         geometry.attributes.position.needsUpdate = true
         geometry.computeBoundingSphere()
         return geometry
     }
}

const geometry = ({cube}) => {
    return <primitive object={cube.geometry} />
}

I’m ending up with a lot of code in my stores which I feel should be in the component. And I know you can’t avoid creating new instances because of the nature of three.js. But what I’m thinking is maybe if the component could have an update function, which react-three-fiber could use instead of reinstantiating the object on render.

Something like this would keep that logic inside the component and feels a little nicer:

class CubeStore {
    @observable x = 0
    @observable y = 0
    @observable z = 0

    constructor(x,y,z) {
        this.x = x
        this.y = y
        this.z = z
    }
}

const geometry = ({cube}) => {
    ref = useRef()
    // use this on update instead of creating a new geometry instance
    useImperativeUpdate( 
        () => {
             const geometry = ref.current
             geometry.addAttribute('position', getCubeVertices(cube.x, cube.y, cube.z))
             geometry.attributes.position.needsUpdate = true
             geometry.computeBoundingSphere()
        }, 
        [cube.x, cube.y, cube.z] // execute only if these change
    )
    return <bufferGeometry ref={ref} ... />
}

What’s your thoughts on something like that?

Issue Analytics

  • State:closed
  • Created 5 years ago
  • Reactions:1
  • Comments:15 (15 by maintainers)

github_iconTop GitHub Comments

1reaction
drcmdacommented, Mar 21, 2019

useImperativeUpdate is a nice idea btw, it could still be useful.

I don’t see how yours would work, you don’t pass a ref. It could return one maybe?

const ref = useUpdate( 
  geometry => {
    geometry.addAttribute('position', getCubeVertices(cube.x, cube.y, cube.z))
    geometry.attributes.position.needsUpdate = true
    geometry.computeBoundingSphere()
  }, 
  [cube.x, cube.y, cube.z] // execute only if these change
)
return <bufferGeometry ref={ref} />

Or, accept one as the 3rd param optionally, so that you can re-use refs for multiple purposes

const ref = useRef()
useUpdate(() => {}, [...], ref)
return <bufferGeometry ref={ref} />
0reactions
drcmdacommented, Mar 30, 2019

There was indeed a bug, onUpdate was called too early.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Declarative APIs in an Imperative World - InfoQ
In this example, we only want to update if a panel is being hidden or shown. We don't care about those other props....
Read more >
Naming conventions | Cloud APIs
The verb portion of the method name should use the imperative mood, which is for orders or commands rather than the indicative mood...
Read more >
Apollo Client's new imperative store API - Apollo GraphQL Blog
Apollo Client's new imperative store API ... These methods allow you to update the data in your local cache, to simulate an update...
Read more >
Hooks API Reference - React
useEffect. useEffect(didUpdate); Accepts a function that contains imperative, possibly effectful code. Mutations, subscriptions, timers, logging, and other ...
Read more >
Add Imperative Slot API by mfreed7 · Pull Request #966 - GitHub
This is a fresh PR, with updates from #860. I don't have permissions to update that PR, and the master-to-main transition made it...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found