Unblock React Compiler for 5 components with early exits inside try (#11547)

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Tomasz Zawadzki
2026-08-31 15:52:17 +02:00
committed by GitHub
parent f9cf58ea44
commit a086a2ebe0
5 changed files with 45 additions and 18 deletions
+6 -6
View File
@@ -21,12 +21,12 @@ export function useGoogleTranslate() {
if (IS_ANDROID) { if (IS_ANDROID) {
try { try {
// use `getApplicationIconAsync` to determine if the translate app is installed // use `getApplicationIconAsync` to determine if the translate app is installed
if ( const installed = await IntentLauncher.getApplicationIconAsync(
!(await IntentLauncher.getApplicationIconAsync( 'com.google.android.apps.translate',
'com.google.android.apps.translate', )
)) if (!installed) {
) { openLink(translateUrl)
throw new Error('Translate app not installed') return
} }
// TODO: this should only be called one at a time, use something like // TODO: this should only be called one at a time, use something like
@@ -83,10 +83,10 @@ export function BetaFeaturesSettingsScreen({}: Props) {
} catch (e) { } catch (e) {
logger.error('Failed to toggle beta features', {safeMessage: e}) logger.error('Failed to toggle beta features', {safeMessage: e})
Toast.show(l`Something went wrong, please try again.`, {type: 'error'}) Toast.show(l`Something went wrong, please try again.`, {type: 'error'})
return
} finally {
setIsPending(false) setIsPending(false)
return
} }
setIsPending(false)
/* /*
* The toggle already succeeded; re-evaluate feature gates against the new * The toggle already succeeded; re-evaluate feature gates against the new
* attribute in-session as a best-effort follow-up. A failure here should * attribute in-session as a best-effort follow-up. A failure here should
+4 -3
View File
@@ -76,10 +76,11 @@ export function StepHandle() {
dispatch({type: 'setIsLoading', value: true}) dispatch({type: 'setIsLoading', value: true})
const serviceDid = state.serviceDescription?.did ?? 'UNKNOWN'
try { try {
const {available: handleAvailable} = await checkHandleAvailability( const {available: handleAvailable} = await checkHandleAvailability(
createFullHandle(handle, state.userDomain), createFullHandle(handle, state.userDomain),
state.serviceDescription?.did ?? 'UNKNOWN', serviceDid,
{}, {},
) )
@@ -90,6 +91,7 @@ export function StepHandle() {
value: _(msg`That username is already taken`), value: _(msg`That username is already taken`),
field: 'handle', field: 'handle',
}) })
dispatch({type: 'setIsLoading', value: false})
return return
} else { } else {
ax.metric('signup:handleAvailable', {typeahead: false}) ax.metric('signup:handleAvailable', {typeahead: false})
@@ -99,9 +101,8 @@ export function StepHandle() {
safeMessage: error, safeMessage: error,
}) })
// do nothing on error, let them pass // do nothing on error, let them pass
} finally {
dispatch({type: 'setIsLoading', value: false})
} }
dispatch({type: 'setIsLoading', value: false})
ax.metric('signup:nextPressed', { ax.metric('signup:nextPressed', {
activeStep: state.activeStep, activeStep: state.activeStep,
+4 -3
View File
@@ -322,6 +322,7 @@ export function useSubmitSignup() {
dispatch({type: 'setError', value: ''}) dispatch({type: 'setError', value: ''})
dispatch({type: 'setIsLoading', value: true}) dispatch({type: 'setIsLoading', value: true})
const verificationCode = state.pendingSubmit?.verificationCode
try { try {
await createAccount( await createAccount(
{ {
@@ -331,7 +332,7 @@ export function useSubmitSignup() {
password: state.password, password: state.password,
birthDate: state.dateOfBirth, birthDate: state.dateOfBirth,
inviteCode: state.inviteCode.trim(), inviteCode: state.inviteCode.trim(),
verificationCode: state.pendingSubmit?.verificationCode, verificationCode,
}, },
{ {
signupDuration: Date.now() - state.signupStartTime, signupDuration: Date.now() - state.signupStartTime,
@@ -360,6 +361,7 @@ export function useSubmitSignup() {
field: 'invite-code', field: 'invite-code',
}) })
dispatch({type: 'setStep', value: SignupStep.INFO}) dispatch({type: 'setStep', value: SignupStep.INFO})
dispatch({type: 'setIsLoading', value: false})
return return
} }
@@ -384,9 +386,8 @@ export function useSubmitSignup() {
safeMessage: e, safeMessage: e,
}) })
} }
} finally {
dispatch({type: 'setIsLoading', value: false})
} }
dispatch({type: 'setIsLoading', value: false})
}, },
[l, ax, createAccount, onboardingDispatch], [l, ax, createAccount, onboardingDispatch],
) )
+29 -4
View File
@@ -10,6 +10,25 @@ import {updatePostShadow} from '../cache/post-shadow'
import {useAppviewClient, useSession} from '../session' import {useAppviewClient, useSession} from '../session'
import {useProfileUpdateMutation} from './profile' import {useProfileUpdateMutation} from './profile'
/**
* Out of the hook because React Compiler cannot lower a `throw` inside a `try`.
* Keeping the check in place - rather than hoisting it above the `try` - means
* the catch below still shows its toast and reverts the optimistic update.
*/
function assertSignedIn(account: unknown): asserts account {
if (!account) throw new Error('Not signed in')
}
/**
* Out of the hook because React Compiler cannot lower an optional chain inside a
* `try` block, and `profile` only exists once the request inside it resolves.
*/
function getPinnedPostUri(profile: {
pinnedPost?: {uri: string}
}): string | undefined {
return profile.pinnedPost?.uri
}
export function usePinnedPostMutation() { export function usePinnedPostMutation() {
const {_} = useLingui() const {_} = useLingui()
const {currentAccount} = useSession() const {currentAccount} = useSession()
@@ -33,13 +52,19 @@ export function usePinnedPostMutation() {
updatePostShadow(queryClient, postUri, {pinned: pinCurrentPost}) updatePostShadow(queryClient, postUri, {pinned: pinCurrentPost})
// get the currently pinned post so we can optimistically remove the pin from it // get the currently pinned post so we can optimistically remove the pin from it
if (!currentAccount) throw new Error('Not signed in') assertSignedIn(currentAccount)
const profile = await client.call(app.bsky.actor.getProfile, { const profile = await client.call(app.bsky.actor.getProfile, {
actor: currentAccount.did, actor: currentAccount.did,
}) })
prevPinnedPost = profile.pinnedPost?.uri prevPinnedPost = getPinnedPostUri(profile)
if (prevPinnedPost && prevPinnedPost !== postUri) { if (prevPinnedPost) {
updatePostShadow(queryClient, prevPinnedPost, {pinned: false}) /*
* Nested rather than `&&`: React Compiler cannot lower a logical
* expression in a test position inside a `try`.
*/
if (prevPinnedPost !== postUri) {
updatePostShadow(queryClient, prevPinnedPost, {pinned: false})
}
} }
await profileUpdateMutate({ await profileUpdateMutate({