此悬念边界在完成水合之前收到了更新。 React Native、Expo 路由器、Redux、Supabase

问题描述 投票:0回答:1

在 Expo 上启动开发服务器,在 localhost:8081 上的浏览器上打开,期望应用程序呈现,但出现错误:

This Suspense boundary received an update before it finished hydrating. This caused the boundary to switch to client rendering. The usual way to fix this is to wrap the original update in startTransition.
Call Stack
updateDehydratedSuspenseComponent
node_modules/react-dom/cjs/react-dom.development.js
updateSuspenseComponent
node_modules/react-dom/cjs/react-dom.development.js
beginWork
node_modules/react-dom/cjs/react-dom.development.js
beginWork$1
node_modules/react-dom/cjs/react-dom.development.js
performUnitOfWork
node_modules/react-dom/cjs/react-dom.development.js
workLoopSync
node_modules/react-dom/cjs/react-dom.development.js
renderRootSync
node_modules/react-dom/cjs/react-dom.development.js
performSyncWorkOnRoot
node_modules/react-dom/cjs/react-dom.development.js
flushSyncCallbacks
node_modules/react-dom/cjs/react-dom.development.js
commitRootImpl
http://localhost:8081/node_modules%5Cexpo-router%5Centry.bundle
commitRoot
node_modules/react-dom/cjs/react-dom.development.js
finishConcurrentRender
node_modules/react-dom/cjs/react-dom.development.js
performConcurrentWorkOnRoot
node_modules/react-dom/cjs/react-dom.development.js
workLoop
node_modules/scheduler/cjs/scheduler.development.js
flushWork
node_modules/scheduler/cjs/scheduler.development.js
performWorkUntilDeadline
node_modules/scheduler/cjs/scheduler.development.js
Collapse all 16 frames

保存时内容显示正确,但每次重新加载时都会出现水合错误。 Anroid 手机上的 Expo Go 没有错误。

难以查明问题。几天前重新加载可以正常工作。

expo-router结构:

app
|   +html.tsx
|   +not-found.tsx
|   _layout.tsx
|
+---(app)
|   |   add-item.tsx
|   |   modal.tsx
|   |   _layout.tsx
|   |
|   \---(tabs)
|           account.tsx
|           items.tsx
|           _layout.tsx
|
\---(auth)
        login.tsx
        _layout.tsx

_layout.tsx 位于应用程序文件夹的根目录:

import React from 'react'
import { Provider } from 'react-redux'
import { store } from '@/src/redux/store'
import { ThemeProvider } from '@react-navigation/native'
import { useFonts } from 'expo-font'
import FontAwesome from '@expo/vector-icons/FontAwesome'
import { Slot } from 'expo-router'
import * as SplashScreen from 'expo-splash-screen'
import { useEffect } from 'react'
import { useColorScheme } from '@/src/components/useColorScheme'
import { useRouter } from 'expo-router'
import { DarkTheme, DefaultTheme } from '@react-navigation/native'
import { supabase } from '@/src/utils/supabase'
import { useAppDispatch } from '@/src/redux/hooks'
import { logout, setSession } from '@/src/redux/userSlice'

export const unstable_settings = {
  initialRouteName: '(tabs)',
}

SplashScreen.preventAutoHideAsync()

export default function RootLayout() {
  const [loaded, error] = useFonts({
    SpaceMono: require('../assets/fonts/SpaceMono-Regular.ttf'),
    ...FontAwesome.font,
  })

  useEffect(() => {
    if (error) throw error
  }, [error])

  useEffect(() => {
    if (loaded) {
      SplashScreen.hideAsync()
    }
  }, [loaded])

  if (!loaded) {
    return null
  }

  return (
    <Provider store={store}>
      <App />
    </Provider>
  )
}

function App() {
  const colorScheme = useColorScheme()
  const router = useRouter()
  const dispatch = useAppDispatch()

  useEffect(() => {
    supabase.auth.getSession().then(({ data: { session } }) => {
      if (session) {
        dispatch(setSession(session))
        router.replace('/(app)/(tabs)/items')
      } else {
        console.log('no user')
      }
    })

    supabase.auth.onAuthStateChange((_event, session) => {
      if (session) {
        dispatch(setSession(session))
        router.replace('/(app)/(tabs)/items')
      } else {
        console.log('no user')
        dispatch(logout())
        router.replace('/(auth)/login')
      }
    })
  }, [])

  return (
    <ThemeProvider value={colorScheme === 'dark' ? DarkTheme : DefaultTheme}>
      <Slot />
    </ThemeProvider>
  )
}

items.tsx,redux 使用示例:

import { useEffect } from 'react'
import { selectCatalog, setItems } from '@/src/redux/catalogSlice'
import { View, Pressable, StyleSheet, SafeAreaView } from 'react-native'
import SoldItemList from '@/src/components/SoldItemList'
import { Link } from 'expo-router'
import { Text } from '@/src/components/Themed'
import { Item } from '@/src/types/ItemInterface'
import { data } from '@/assets/data'
import { useAppDispatch, useAppSelector } from '@/src/redux/hooks'

export default function Items() {
  const dispatch = useAppDispatch()
  const user = useAppSelector((state) => state.user.session?.user)
  const catalog: Item[] = useAppSelector(selectCatalog)


  useEffect(() => {
    if (catalog.length === 0) {
      dispatch(setItems(data))
    }
  }, [catalog, dispatch])

  return (
    <SafeAreaView style={styles.container}>
      <View style={styles.content}>
        <Text> User: {user?.email ? user.email : null}</Text>
        <SoldItemList items={catalog} />
        <View>
          <Link href='/add-item' asChild>
            <Pressable style={styles.button}>
              <Text
                lightColor='rgba(255,255,255,0.8)'
                darkColor='rgba(255,255,255,0.8)'
              >
                Add item
              </Text>
            </Pressable>
          </Link>
        </View>
      </View>
    </SafeAreaView>
  )
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    alignItems: 'center',
    justifyContent: 'center',
  },
  content: {
    flex: 1,
    width: '100%',
    maxWidth: 550,
    alignItems: 'center',
    justifyContent: 'center',
  },
  button: {
    alignItems: 'center',
    justifyContent: 'center',
    paddingVertical: 12,
    paddingHorizontal: 32,
    borderRadius: 4,
    elevation: 3,
    backgroundColor: '#910A67',
    maxWidth: 200,
  },
})

删除了项目并返回了几次迭代,npm install & npm cache clean --force & npx expo start --clear,但错误仍然存在。切换浏览器并尝试隐身模式。

package.json:

{
  "name": "expo-app",
  "main": "expo-router/entry",
  "version": "1.0.0",
  "scripts": {
    "start": "expo start",
    "android": "expo start --android",
    "ios": "expo start --ios",
    "web": "expo start --web",
    "test": "jest --watchAll"
  },
  "jest": {
    "preset": "jest-expo"
  },
  "dependencies": {
    "@expo/vector-icons": "^14.0.0",
    "@react-native-async-storage/async-storage": "^1.21.0",
    "@react-navigation/native": "^6.0.2",
    "@reduxjs/toolkit": "^2.2.2",
    "@supabase/supabase-js": "^2.40.0",
    "@testing-library/react-native": "^12.4.4",
    "expo": "~50.0.14",
    "expo-font": "~11.10.3",
    "expo-linking": "~6.2.2",
    "expo-router": "~3.4.8",
    "expo-splash-screen": "~0.26.4",
    "expo-status-bar": "~1.11.1",
    "expo-system-ui": "~2.9.3",
    "expo-web-browser": "~12.8.2",
    "react": "18.2.0",
    "react-dom": "18.2.0",
    "react-native": "0.73.6",
    "react-native-elements": "^3.4.3",
    "react-native-safe-area-context": "4.8.2",
    "react-native-screens": "~3.29.0",
    "react-native-url-polyfill": "^2.0.0",
    "react-native-uuid": "^2.0.2",
    "react-native-web": "~0.19.6",
    "react-redux": "^9.1.0"
  },
  "devDependencies": {
    "@babel/core": "^7.20.0",
    "@types/jest": "^29.5.12",
    "@types/react": "~18.2.45",
    "jest": "^29.2.1",
    "jest-expo": "~50.0.4",
    "react-native-dotenv": "^3.4.11",
    "react-test-renderer": "18.2.0",
    "typescript": "^5.1.3"
  },
  "private": true
}
react-native redux expo environment-variables hydration
1个回答
0
投票

哇,这真是一种享受。该错误是由于将.env与第三方插件react-native-dotenv一起使用,而不是使用带有EXPO_PUBLIC前缀的Expo引起的:https://docs.expo.dev/guides/environment-variables/

© www.soinside.com 2019 - 2024. All rights reserved.