aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar Kristóf Marussy <kristof@marussy.com>2022-05-08 23:10:29 +0200
committerLibravatar Kristóf Marussy <kristof@marussy.com>2022-05-16 00:55:03 +0200
commitc96b88b66097d58f901be4ae2831883b7472ca86 (patch)
tree50e1226e43a0cf993fc2bac8673c0e9c5796ce7d
parentfix: vite dev server race condition (diff)
downloadsophie-c96b88b66097d58f901be4ae2831883b7472ca86.tar.gz
sophie-c96b88b66097d58f901be4ae2831883b7472ca86.tar.zst
sophie-c96b88b66097d58f901be4ae2831883b7472ca86.zip
fix: react suspense race condition
The top-level Suspense might trigger before the StoreProvider sets the store, which causes an error to be thrown in the useStore hook. We pass the store explicitly as a prop into the components that should load before the Suspense, which gets rid of the error. Signed-off-by: Kristóf Marussy <kristof@marussy.com>
-rw-r--r--package.json2
-rw-r--r--packages/renderer/src/components/ThemeProvider.tsx82
-rw-r--r--packages/renderer/src/i18n/RtlCacheProvider.tsx12
-rw-r--r--packages/renderer/src/index.tsx18
4 files changed, 61 insertions, 53 deletions
diff --git a/package.json b/package.json
index ba09979..a43b84b 100644
--- a/package.json
+++ b/package.json
@@ -19,7 +19,7 @@
19 "type": "module", 19 "type": "module",
20 "main": "packages/main/dist/index.cjs", 20 "main": "packages/main/dist/index.cjs",
21 "scripts": { 21 "scripts": {
22 "clean": "rimraf coverage dist packages/*/dist packages/*/*.tsbuildinfo .vite", 22 "clean": "rimraf coverage dist 'packages/*/dist' 'packages/*/*.tsbuildinfo' .vite",
23 "test": "node --experimental-vm-modules --no-warnings $(yarn bin jest)", 23 "test": "node --experimental-vm-modules --no-warnings $(yarn bin jest)",
24 "test:ci": "yarn test --ci --coverage --reporters=default --reporters=jest-junit", 24 "test:ci": "yarn test --ci --coverage --reporters=default --reporters=jest-junit",
25 "test:integ": "electron scripts/electronJest.cjs --user-data-dir=userDataDir/integ --config=jest.integ.config.cjs --runInBand", 25 "test:integ": "electron scripts/electronJest.cjs --user-data-dir=userDataDir/integ --config=jest.integ.config.cjs --runInBand",
diff --git a/packages/renderer/src/components/ThemeProvider.tsx b/packages/renderer/src/components/ThemeProvider.tsx
index 2ea2186..0273234 100644
--- a/packages/renderer/src/components/ThemeProvider.tsx
+++ b/packages/renderer/src/components/ThemeProvider.tsx
@@ -23,48 +23,56 @@ import {
23 ThemeProvider as MuiThemeProvider, 23 ThemeProvider as MuiThemeProvider,
24} from '@mui/material/styles'; 24} from '@mui/material/styles';
25import { observer } from 'mobx-react-lite'; 25import { observer } from 'mobx-react-lite';
26import React from 'react'; 26import React, { type ReactNode } from 'react';
27 27
28import { useStore } from './StoreProvider'; 28import type RendererStore from '../stores/RendererStore';
29 29
30export default observer( 30function ThemeProvider({
31 ({ children }: { children: JSX.Element | JSX.Element[] }) => { 31 children,
32 const { 32 store: {
33 shared: { shouldUseDarkColors, writingDirection }, 33 shared: { shouldUseDarkColors, writingDirection },
34 } = useStore(); 34 },
35 35}: {
36 const theme = createTheme({ 36 children?: ReactNode;
37 direction: writingDirection, 37 store: RendererStore;
38 palette: shouldUseDarkColors 38}) {
39 ? { 39 const theme = createTheme({
40 mode: 'dark', 40 direction: writingDirection,
41 divider: 'rgba(255, 255, 255, 0.22)', 41 palette: shouldUseDarkColors
42 } 42 ? {
43 : { 43 mode: 'dark',
44 mode: 'light', 44 divider: 'rgba(255, 255, 255, 0.22)',
45 divider: 'rgba(0, 0, 0, 0.24)', 45 }
46 }, 46 : {
47 components: { 47 mode: 'light',
48 MuiBadge: { 48 divider: 'rgba(0, 0, 0, 0.24)',
49 styleOverrides: { 49 },
50 standard: { 50 components: {
51 // Reduce badge with to make the unread message badge with "99+" unread messages 51 MuiBadge: {
52 // fit within the sidebar. Applied for all badges for consistency. 52 styleOverrides: {
53 paddingLeft: 4, 53 standard: {
54 paddingRight: 4, 54 // Reduce badge with to make the unread message badge with "99+" unread messages
55 }, 55 // fit within the sidebar. Applied for all badges for consistency.
56 paddingLeft: 4,
57 paddingRight: 4,
56 }, 58 },
57 }, 59 },
58 MuiIconButton: { 60 },
59 styleOverrides: { 61 MuiIconButton: {
60 sizeMedium: { 62 styleOverrides: {
61 padding: 6, 63 sizeMedium: {
62 }, 64 padding: 6,
63 }, 65 },
64 }, 66 },
65 }, 67 },
66 }); 68 },
69 });
67 70
68 return <MuiThemeProvider theme={theme}>{children}</MuiThemeProvider>; 71 return <MuiThemeProvider theme={theme}>{children}</MuiThemeProvider>;
69 }, 72}
70); 73
74ThemeProvider.defaultProps = {
75 children: undefined,
76};
77
78export default observer(ThemeProvider);
diff --git a/packages/renderer/src/i18n/RtlCacheProvider.tsx b/packages/renderer/src/i18n/RtlCacheProvider.tsx
index be770b8..1303314 100644
--- a/packages/renderer/src/i18n/RtlCacheProvider.tsx
+++ b/packages/renderer/src/i18n/RtlCacheProvider.tsx
@@ -21,21 +21,21 @@
21import type { EmotionCache } from '@emotion/cache'; 21import type { EmotionCache } from '@emotion/cache';
22import { CacheProvider } from '@emotion/react'; 22import { CacheProvider } from '@emotion/react';
23import { observer } from 'mobx-react-lite'; 23import { observer } from 'mobx-react-lite';
24import React, { ReactNode } from 'react'; 24import React, { type ReactNode } from 'react';
25 25
26import { useStore } from '../components/StoreProvider'; 26import type RendererStore from '../stores/RendererStore';
27 27
28function RtlCacheProvider({ 28function RtlCacheProvider({
29 children, 29 children,
30 store: {
31 shared: { writingDirection },
32 },
30 rtlCache, 33 rtlCache,
31}: { 34}: {
32 children?: ReactNode; 35 children?: ReactNode;
36 store: RendererStore;
33 rtlCache: EmotionCache; 37 rtlCache: EmotionCache;
34}): JSX.Element { 38}): JSX.Element {
35 const {
36 shared: { writingDirection },
37 } = useStore();
38
39 return writingDirection === 'rtl' ? ( 39 return writingDirection === 'rtl' ? (
40 <CacheProvider value={rtlCache}>{children}</CacheProvider> 40 <CacheProvider value={rtlCache}>{children}</CacheProvider>
41 ) : ( 41 ) : (
diff --git a/packages/renderer/src/index.tsx b/packages/renderer/src/index.tsx
index 726e00e..9971469 100644
--- a/packages/renderer/src/index.tsx
+++ b/packages/renderer/src/index.tsx
@@ -74,16 +74,16 @@ const App = lazy(() => import('./components/App'));
74function Root(): JSX.Element { 74function Root(): JSX.Element {
75 return ( 75 return (
76 <React.StrictMode> 76 <React.StrictMode>
77 <StoreProvider store={store}> 77 <RtlCacheProvider store={store} rtlCache={rtlCache}>
78 <RtlCacheProvider rtlCache={rtlCache}> 78 <ThemeProvider store={store}>
79 <ThemeProvider> 79 <CssBaseline enableColorScheme />
80 <CssBaseline enableColorScheme /> 80 <Suspense fallback={<Loading />}>
81 <Suspense fallback={<Loading />}> 81 <StoreProvider store={store}>
82 <App devMode={isDevelopment} /> 82 <App devMode={isDevelopment} />
83 </Suspense> 83 </StoreProvider>
84 </ThemeProvider> 84 </Suspense>
85 </RtlCacheProvider> 85 </ThemeProvider>
86 </StoreProvider> 86 </RtlCacheProvider>
87 </React.StrictMode> 87 </React.StrictMode>
88 ); 88 );
89} 89}