Dexie useLiveQuery hook causes the error "TypeError: dexie.liveQuery is not a function" - dexie

Did an npm install of dexie and dexie-react-hooks yesterday. package-lock.json shows dexie 3.0.3 and dexie-react-hooks 1.0.7
Created a react app using the template "cra-template-pwa"
Used the docs on the Dexie site for basic Dexie DB and useLiveQuery and created this simple app component in React.
import React from 'react';
import Dexie from 'dexie'
import { useLiveQuery } from 'dexie-react-hooks'
const myDb = new Dexie('myTable');
myDb.version(1).stores(
{
items: "id,name,startDate,endDate"
}
)
function App() {
const items = useLiveQuery(myDb.items.orderBy('name'), []);
const itemViews = items.map(item => { return <div>{item.name}</div> })
return (
<div className="App">
<ul>
{itemViews}
</ul>
</div>
);
}
export default App;
When this runs in the browser, the app can't display and instead we get this error:
TypeError: dexie.liveQuery is not a function
(anonymous function)
src/dexie-react-hooks.ts:14
11 | // Make it remember previous subscription's default value when
12 | // resubscribing (รก la useTransition())
13 | let currentValue = lastResult;
> 14 | const observable = liveQuery(querier);
| ^ 15 | return {
16 | getCurrentValue: () => currentValue,
17 | subscribe: (onNext, onError) => {
Are we doing something wrong, or is this a bug?

You still need to install dexie#next to use it (as of October 2021). A new stable version of dexie with liveQuery support is coming out soon.
yarn add dexie#next dexie-react-hooks#latest
or
npm i dexie#next dexie-react-hooks#latest

Related

Is it possible to use the layout in the _app.jsx component with next-i18next?

To create a site, I use nextjs, when creating pages, I took the general layout with the header and footer into a separate hoc component and wrapped the page components in the file with it _app.jsx:
function App({ Component, ...rest }) {
const { store, props } = wrapper.useWrappedStore(rest)
return (
<Provider store={store}>
<Layout>
<Component {...props.pageProps} />
</Layout>
</Provider>
)
}
Everything worked fine until localization became a problem, after using the next-18next library for translations and adding serverSideTranslations, two errors began to appear on each page:
react-i18next:: You will need to pass in an i18next instance by using initReactI18next
frontend-node_1 | TypeError: Cannot read properties of undefined (reading 'label')
frontend-node_1 | at DropdownSwitcher (webpack-internal:///./src/components/header/translation/DropdownSwitcher.jsx:45:36)
frontend-node_1 | at renderWithHooks (/app/node_modules/react-dom/cjs/react-dom-server.browser.development.js:5658:16)
frontend-node_1 | at renderIndeterminateComponent (/app/node_modules/react-dom/cjs/react-dom-server.browser.development.js:5731:15)
frontend-node_1 | at renderElement (/app/node_modules/react-dom/cjs/react-dom-server.browser.development.js:5946:7)
frontend-node_1 | at renderMemo (/app/node_modules/react-dom/cjs/react-dom-server.browser.development.js:5868:3)
frontend-node_1 | at renderElement (/app/node_modules/react-dom/cjs/react-dom-server.browser.development.js:6011:11)
frontend-node_1 | at renderNodeDestructiveImpl (/app/node_modules/react-dom/cjs/react-dom-server.browser.development.js:6104:11)
frontend-node_1 | at renderNodeDestructive (/app/node_modules/react-dom/cjs/react-dom-server.browser.development.js:6076:14)
frontend-node_1 | at renderNode (/app/node_modules/react-dom/cjs/react-dom-server.browser.development.js:6259:12)
frontend-node_1 | at renderHostElement (/app/node_modules/react-dom/cjs/react-dom-server.browser.development.js:5642:3)
The error with "label" occurs because the i18n object is empty on the server:
const DropdownSwitcher = () => {
const { i18n } = useTranslation()
const currentLanguage = useMemo(() => { // language as undefined
return LANGUAGES.find((item) => item.language === i18n.language)
}, [i18n.language])
....
But everything is fine on the client and there are no errors. What could be the reason and how to fix it, since the App itself from the _app.jsx file is wrapped in appWithTranslation from next-i18next.
Therefore, two questions arise, how to fix react-i18next:: You will need to pass in an i18next instance by using initReactI18next and why there is no i18n object on the server?
I moved the layout to the level of the page itself, removing it from _app.js, but for some reason, then something, useEffect() is repeated in the header, although the header component has not changed in any way and bringing the layout to the level of _app.jsx fixes it
If there is not enough information or you need a visual example, I will try to create a small program that demonstrates this with open source. Please write in a comment.
I solved my problem, but I forgot to provide an answer here, but I noticed that someone also has this problem, so I will try to help people who come across this post, although it is relevant only for nextjs version 12, since with the appearance of version 14, the structure there has improved a lot with as I think there should be no more questions like mine.
1. Rendering the layout
In the official doc, there is a whole section that describes how to correctly divide the layout so that it works according to the SPA type.
pages/index.jsx
// pages/index.jsx
import Layout from '../components/layout'
import NestedLayout from '../components/nested-layout'
export default function Page() {
return (
/** Your content */
)
}
Page.getLayout = function getLayout(page) {
return (
<Layout>
<NestedLayout>{page}</NestedLayout>
</Layout>
)
}
pages/_app.js
// pages/_app.js
export default function MyApp({ Component, pageProps }) {
// Use the layout defined at the page level, if available
const getLayout = Component.getLayout || ((page) => page)
return getLayout(<Component {...pageProps} />)
}
This component method approach is much better than using its direction in _app.jsx because you can extend or replace them and not make a crude monolith, example how I used it:
// pages/ingex.jsx
function HomePage() {
return (
<HomeLayout>
<Main />
</HomeLayout>
)
}
HomePage.getLayout = (page) => <MainLayout>{page}</MainLayout>
// pages/about-us.jsx
const AboutUsPage = () => {
return (
<>
<HomeLayout>
<AboutUs />
</HomeLayout>
</>
)
}
AboutUsPage.getLayout = (page) => (
<MainLayout withNav>
<LayoutContext.Consumer>
{({ device }) => device.isMobile && <NavigationMobile />}
</LayoutContext.Consumer>
{page}
</MainLayout>
)
With this approach, react still works like a spa and a similar page to about-us, which will also have NavigationMobile, will simply compare it.
2. Error with next-i18next
The whole point was that the next-i18next library was configured incorrectly in the first place (more precisely, it needed to be corrected). In order to configure everything correctly, I had to do the following:
- Move the folder with translation files to the public folder. This is necessary so that the library config, which we will configure a little below, can see the translation files and interact with them
- Configure next-i18next.config.js to work with the client. Here is an example setup with some comments. And also a link to the documentation, and some other resources I found while setting up.
next-i18next.config.js
const path = require('path')
const LANGUAGES = ['en', 'pl', 'uk']
const DEFAULT_LANGUAGE = 'en'
// if it is the server, then the full path, if the client, then the relative path.
const localePath =
typeof window === 'undefined' ? path.resolve('public', 'translation') : '/public/translation'
module.exports = {
i18n: {
defaultLocale: DEFAULT_LANGUAGE,
locales: LANGUAGES,
fallbackLng: LANGUAGES,
nsSeparator: '::',
keySeparator: '::',
// How to use libraries for i18next like LanguageDetector
use: [require('i18next-intervalplural-postprocessor')],
serializeConfig: false,
},
localePath: localePath,
}
- Configure next-i18next in the _app.jsx file. Here everything is as described in the documentation.
import { appWithTranslation } from 'next-i18next'
import nextI18NextConfig from '../../next-i18next.config'
function App({ Component, ...rest }) {
const { store, props } = wrapper.useWrappedStore(rest)
const getLayout = Component.getLayout || ((page) => page)
//WARNING!!! You don't have to have your own i18next initialization like i18next.use(LanguageDetector).use(intervalPlural).init({ detection: options }) this is all done by the next-i18next library
return (
<Provider store={store}>
<AppHOC>{getLayout(<Component {...props.pageProps} />)}</AppHOC>
</Provider>
)
}
export default appWithTranslation(App, nextI18NextConfig)
- You need to pass the config when calling the serverSideTranslations function. To make your life easier, it is better to transfer the implementation of this function to another file, here is an example of how I did it:
// utils/serverSideTranslations.js
import { serverSideTranslations as baseServerSideTranslations } from 'next-i18next/serverSideTranslations'
import { dt } from '../../constants/defaultTranslate'
import { DEFAULT_LANGUAGE } from '../../constants/languages'
import nextI18NextConfig from '../../../next-i18next.config.js'
const serverSideTranslations = async (locale, domains = []) => {
return await baseServerSideTranslations(locale, [...dt, ...domains], nextI18NextConfig, [
DEFAULT_LANGUAGE,
])
}
export default serverSideTranslations
- And finally, use this function on the pages.
import MainLayout from '../components/layouts/MainLayout'
import serverSideTranslations from '../utils/serverSideTranslations'
import HomeLayout from '../components/home/HomeLayout'
import Main from '../components/home/main/Main'
function HomePage() {
return (
<HomeLayout>
<Main />
</HomeLayout>
)
}
HomePage.getLayout = (page) => <MainLayout>{page}</MainLayout>
export const getServerSideProps = async ({ locale }) => {
// Wrapping in Promis.all is not necessary, I use it simply so that if there are any other asynchronous operations, then not to use them through await and not to block each other's work
const [translations] = await Promise.all([
serverSideTranslations(locale, ['home']),
])
return {
props: {
...translations,
},
}
}
export default HomePage
I hope this helped someone, if you have any comments, write in the comments

How to use useI18n inside vue3 composition api?

I'm using vue-i18n in conjunction with quasar + vue 3 composition api but I get an error as following
SyntaxError: 19 vendor.49822a76.js:formatted:926 SyntaxError: 19 (at vendor.49822a76.js:formatted:27825:21)
at F (vendor.49822a76.js:formatted:27825:21)
at Pt (vendor.49822a76.js:formatted:29590:20)
at vn (vendor.49822a76.js:formatted:30617:27)
at 238.35491042.js:1:419
at f (vendor.49822a76.js:formatted:883:25)
at p (vendor.49822a76.js:formatted:892:27)
Error In console when using useI18n
and here is my i18n file:
Boot directory:
import { boot } from 'quasar/wrappers'
import { createI18n } from 'vue-i18n'
import messages from 'src/i18n'
export default boot(({ app }) => {
const i18n = createI18n({
locale: 'ar',
messages
})
// Set i18n instance on app
app.use(i18n)
})
My Vue File
import { useI18n } from 'vue-i18n';
import AppService from "../../services/api";
export default defineComponent({
setup() {
const { t } = useI18n();
console.log(t)
}
})
any clue?
You need specify allowComposition: true to createI18n options.
Here is the link to the documentaion

Uncaught RangeError: Maximum call stack size exceeded at wrapperRaf at any animation

I installed Ant Design with npm install antd, and mounted the Switch component.
My component is:
import React, { useState } from 'react';
import { Switch } from 'antd';
const FullWidthToggle = (isEnabled) => {
const [isChecked, setIsChecked] = useState(isEnabled);
const onChange = (isChecked) => {
setIsChecked(!isChecked)
}
return (
<div className='full-width-toggle'>
<p> <strong>{isChecked ? 'enabled' : 'disabled'}</strong> </p>
<Switch onChange={onChange}/>
</div>
)
}
export default FullWidthToggle;
Any time I switch, the toggle and the text changes, but I get this error in the console:
Uncaught RangeError: Maximum call stack size exceeded at wrapperRaf
I get the same error with the Collapse component, and I suppose with every animation.
I suspect I need to install or configure something else, can someone tell me what?
I found the answer in the meantime here:
https://github.com/vueComponent/ant-design-vue/issues/1219
I had to add
resolve: {
...
alias: {
...
raf: 'node_modules/raf/',
},
},
to my webpack.config.js file

ReactNative navigation 5 - how to obtain `navigation.state.params` (upgrade from 1.x)

Trying to update old react navigation 1.x to current version 5.x.
I need to display different tab icon depend on what value is in navigation.state.params, that were used in 1.x version. This value is set in one of the screen using navigation.dispatch(data).
this is simplified code used with navigation 1.x:
import {TabBarBottom, TabNavigator} from 'react-navigation';
import {MyIcon, AnotherIcon} from './icons.js';
export default TabNavigator({
Home: {screen: HomeRouter},
Profile: {screen: ProfileRouter},
}, {
navigationOptions: ({navigation}) => ({
tabBarIcon: ({focused}) => {
const {routeName, params} = navigation.state;
...
if (params.data === 1) {
return <AnotherIcon />
}
...
return <MyIcon />;
},
}),
tabBarComponent: TabBarBottom,
tabBarPosition: 'bottom',
});
how need to be change to work with React navigation v.5.x? or all I could do is to use React.Context?
You can get the params using the new hook useRoute available in v5.x
Documentation here

ionic 2 caching images

I am writing an ionic 2 application, and want to cache images.
After long searching on the web I found these references:
https://gist.github.com/ozexpert/d95677e1fe044e6173ef59840c9c484e
https://github.com/chrisben/imgcache.js/blob/master/js/imgcache.js
I implemented the given solution, but i see that the ImgCache module does not behave as expected - the ImgCache.isCached callback is never called.
Any idea or other good solution for caching images in ionic 2?
======== UPDATE ==========
Here is the directive code I use:
import { Directive, ElementRef, Input } from '#angular/core';
import ImgCache from 'imgcache.js';
#Directive({
selector: '[image-cache]'
})
export class ImageCacheDirective {
constructor (
private el: ElementRef
) {
// init
}
ngOnInit() {
// This message is shown in console
console.log('ImageCacheDirective *** ngOnInit: ', this.el.nativeElement.src);
this.el.nativeElement.crossOrigin = "Anonymous"; // CORS enabling
ImgCache.isCached(this.el.nativeElement.src, (path: string, success: any) => {
// These message are never printed
console.log('path - '+ path);
console.log('success - '+ success);
if (success) {
// already cached
console.log('already cached so using cached');
ImgCache.useCachedFile(this.el.nativeElement);
} else {
// not there, need to cache the image
console.log('not there, need to cache the image - ' + this.el.nativeElement.src);
ImgCache.cacheFile(this.el.nativeElement.src, () => {
console.log('cached file');
// ImgCache.useCachedFile(el.nativeElement);
});
}
});
}
}
In app.nodule.es I do:
import { ImageCacheDirective } from '../components/image-cache-directive/image-cache-directive';
and then in home.html:
<img src="http://localhost/ionic-test/img/timeimg.php" image-cache>
It's late but probably this is the solution:
1. Install cordova FileTransfer:
ionic plugin add cordova-plugin-file-transfer --save
2. Init ImgCache when the deviceready event of cordova fires. In src/app/app.component.ts add these methods (or integrate them with your initializeApp() method - this method comes up with a default project start):
initImgCache() {
// activated debug mode
ImgCache.options.debug = true;
ImgCache.options.chromeQuota = 100 * 1024 * 1024; // 100 MB
ImgCache.init(() => { },
() => { console.log('ImgCache init: error! Check the log for errors'); });
}
initializeApp() {
this.platform.ready().then(() => {
this.initImgCache();
// Okay, so the platform is ready and our plugins are available.
// Here you can do any higher level native things you might need.
StatusBar.styleDefault();
Splashscreen.hide();
});
}
Another option is to use a dedicated cache manager for ionic. instead of implementing everything on your own.
Here are 2 options :
1. A generic cache implementation :https://github.com/Nodonisko/ionic-cache
2. This one is better for images: https://github.com/BenBBear/ionic-cache-src
EDIT:
This is not a "link only" answer.. it tells the user to use a ready made implementations instead of trying to implement from scratch.

Resources