-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
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
feat: React 19 support #2349
base: next
Are you sure you want to change the base?
feat: React 19 support #2349
Conversation
|
The latest updates on your projects. Learn more about Vercel for Git ↗︎
|
targets/three/src/index.ts
Outdated
const host = createHost(primitives, { | ||
// @ts-expect-error r3f related | ||
applyAnimatedValues: applyProps, | ||
}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should probably be a proxy since it is valid to extend
the JSX interface beyond what the THREE
namespace contains.
This used to be pulled in by R3F, but we vendor it upstream as of late. Even though we intend to later migrate changes, it's best to not depend on transient dependencies.
@CodyJasonBennett if you can rebase, i've hopefully fixed the issue with the CI :) |
This comment was marked as resolved.
This comment was marked as resolved.
Test runners are supposed to be calling and awaiting I'm not sure how to test React 19 here without rewriting the test suite or its instrumentation. Maybe an e2e test could work? Ideally CI could test a matrix of types and implementation. |
I've gone through your branch, and I think I've discovered the problems with packages/core/test/setup.ts L52: beforeEach(() => {
isRunning = true
frameCache = new WeakMap()
frameLoop.clear()
raf.clear()
global.mockRaf = createMockRaf()
Globals.assign({
now: global.mockRaf.now,
requestAnimationFrame: global.mockRaf.raf,
colors,
skipAnimation: false,
- // This lets our useTransition hook force its component
- // to update from within an "onRest" handler.
- batchedUpdates: act,
})
}) packages/core/test/setup.ts L142 inside - jest.advanceTimersByTime(1000 / 60)
+ await act(() => jest.advanceTimersByTimeAsync(1000 / 60))
global.mockRaf.step()
// Stop observing after the frame is processed.
for (const value of values) {
removeFluidObserver(value, frameObserver)
}
// Ensure pending effects are flushed.
- flushMicroTasks()
+ await act(() => flushMicroTasks()) That seems to solve the warning. |
The // Apply updates created during render.
const update = updates.current[i]
if (update) {
// Update the injected ref if needed.
replaceRef(ctrl, update.ref)
// When an injected ref exists, the update is postponed
// until the ref has its `start` method called.
if (ctrl.ref) {
ctrl.queue.push(update)
} else {
ctrl.start(update)
}
updates.current[i] = null
} |
Is there an ETA on this one? :) |
I was able to get all the SpringContext related tests to pass by refactoring the context into an standard React Context structure. I'm not totally familiar with ALL the usages of the context in this codebase (but the tests do pass, which with good coverage should indicate feasibility) - So there may have been a valid reason for the Context to be structured as it was. Anyway... this code works for the Context setup, and like i said, the tests pass :). import * as React from 'react'
import { useContext, PropsWithChildren } from 'react'
/**
* This context affects all new and existing `SpringValue` objects
* created with the hook API or the renderprops API.
*/
export interface SpringContext {
/** Pause all new and existing animations. */
pause?: boolean
/** Force all new and existing animations to be immediate. */
immediate?: boolean
}
export const SpringContext = React.createContext<SpringContext>({
pause: false,
immediate: false,
})
export const SpringContextProvider = ({
children,
...props
}: PropsWithChildren<SpringContext>) => {
const inherited = useContext(SpringContext)
// Inherited values are dominant when truthy.
const pause = props.pause ?? inherited.pause ?? false
const immediate = props.immediate ?? inherited.immediate ?? false
// Memoize the context to avoid unwanted renders.
const contextValue = React.useMemo(
() => ({ pause, immediate }),
[pause, immediate]
)
return (
<SpringContext.Provider value={contextValue}>
{children}
</SpringContext.Provider>
)
} Granted some other files were needed to be refactored to allow for this change. Directly ingesting the Context AND it's Provider into one exported variable seemed... strange - Hence why there were many Typescript and tests failing (Assumption on my end). So splitting them out as is standard for Context, seemed to alleviate the problem. If there's a valid reason for the Context to be as... strange... as it is, then another solution will be required. Seeing as this PR and the issue it came from is getting stale, I thought i may as well chip in. |
ALSO - On the testing side of this - Once the context had been "fixed". There was no need for the |
As this PR has literally had 0 movement in months - I've made my own PR #2363. The new PR has the changes i mentioned above additionally. |
Why
Adds forward support for React 19 and R3F v9.
What
Upstream breaking changes are limited to types, and I opt to remove deprecated patterns where able:
useRef<T>()
->useRef<T>(null)
JSX
->React.JSX
(MutableRefObject<T>
->RefObject<T>
useRef
andRefObject
are bugged as immutable in 18.3 types)PropsWithRef -> T(omitted; needs indirection for React 18 + 19 support)(R3F)(omitted; this is not backwards compatible to R3F v8.0)JSX.IntrinsicElements
->ThreeElements
Checklist