I'm trying to retrieve data from a pre-populated database using TypeORM using Expo, imitating this working example (https://dev.to/jgabriel1/expo-sqlite-typeorm-4mn8). It keeps throwing this error;
undefined is not an object (evaluating 'ejRepository.getWordandMean')at src/components/page/dictionarypage.js:32:28 in useCallback$argument_0at src/components/page/dictionarypage.js:32:28 in useCallback$argument_0at [native code]:null in callFunctionReturnFlushedQueue
UPDATE
After some investigation and edits, I've found out ejRepository
on dictionarypage.js is undefined, and context
on connection.tsx is returning an empty object. I'm wondering why.
It seems like the connection is established already.
Here's my updated code
/page/dictionarypage.js
..import { DatabaseConnectionProvider, useDatabaseConnection } from '../../data/connection';import { setinputWord } from '../../actions/action';import { connect } from 'react-redux';function DictionaryScreen(props){ const { inputWord } = props; const { ejRepository } = useDatabaseConnection(); // console.log indicates ejRepository is undefined const [wordData, setwordData] = useState(""), [meanData, setmeanData] = useState("Word and definitions will appear here"); const handleinputWord = async () => { try { const results = await ejRepository.getWordandMean(); //this is where the error is thrown setwordData(results.word); setmeanData(results.mean); } catch (error) { console.log(error) }; return(<DatabaseConnectionProvider><SafeAreaView style={styles.container}><View style={styles.searchContainer}><MaterialCommunityIcons name="text-search" color="white" size={30}/><TextInput style={styles.input} onChangeText={mapDispatchToProps} onSubmitEditing={handleinputWord} value={inputWord} key={inputWord} placeholder='Look up the word (Type exactly)' keyboardType="default" /> <StatusBar style='light' /></View><View style={{flex:40, margin:10, alignItems:"center"}}><Text style={{color:'white',fontSize:30,fontWeight:"bold",margin:10}}> {wordData}</Text><ScrollView><Text style={{color:'white',fontSize:18}}> {meanData}</Text></ScrollView></View><View style={{margin:20, flex:1,alignItems:"center"}}><Text style={{color:"white",fontSize:11}}> Data retrieved from ****</Text></View></SafeAreaView></DatabaseConnectionProvider> ); }const mapStateToProps = state => { return { inputWord: state.inputWord } }const mapDispatchToProps = dispatch => { return { onChangeText: inputWord => dispatch(setinputWord({type: 'updateTextInput', inputWord})) } }export default connect(mapStateToProps, mapDispatchToProps) (DictionaryScreen);
/data/repositories/repository.ts
import { useSelector } from 'react-redux';import { Connection, Repository, Like } from 'typeorm';import { EJmodel } from '../entities/EJmodel';interface RootState{ inputWord: string}export class EJRepository { private ormRepository: Repository<EJmodel>; constructor(connection: Connection) { this.ormRepository = connection.getRepository(EJmodel); } public async getWordandMean(): Promise<EJmodel[]> { const inputWord = useSelector((state: RootState) => state.inputWord); const results = await this.ormRepository.find({word: Like(inputWord)} ); return results }}
/data/entities/EJmodel.ts
import {Entity, PrimaryColumn, Column} from "typeorm";@Entity('ejdict.v1.0')export class EJmodel { @PrimaryColumn({type: 'integer'}) item_id: number; @Column({type: 'text'}) word: string; @Column({type: 'text'}) mean: string; @Column({type: 'integer', select: false}) level: number;}
/data/connection.tsx
import React, {createContext, useCallback, useContext, useEffect, useState} from 'react';import { ActivityIndicator } from 'react-native';import { Connection, createConnection } from 'typeorm';import { EJmodel } from './entities/EJmodel';import { ejdict1621603544180 } from './migration/1621603544180-ejdict';import { EJRepository } from './repositories/repository'; interface DatabaseConnectionContextData { ejRepository: EJRepository; } const DatabaseConnectionContext = createContext<DatabaseConnectionContextData>( {} as DatabaseConnectionContextData, ); export const DatabaseConnectionProvider: React.FC = ({ children }) => { const [connection, setConnection] = useState<Connection | null>(null); const connect = useCallback(async () => { const createdConnection = await createConnection({ type: 'expo', name: "ejdict.v1.0", database: 'ejdictcopy.db', driver: require('expo-sqlite'), entities: [EJmodel], migrations: [ejdict1621603544180], migrationsRun: true, synchronize: false, extra:{ createFromLocation: '/Users/**/**/assets/db/ejdictcopy.db' } }); setConnection(createdConnection); }, []); useEffect(() => { if (!connection) { connect(); } }, [connect, connection]); if (!connection) { return <ActivityIndicator />; } return (<DatabaseConnectionContext.Provider value={{ ejRepository: new EJRepository(connection), }}> {children}</DatabaseConnectionContext.Provider> ); }; export function useDatabaseConnection() { const context = useContext(DatabaseConnectionContext); return context; }
Other files and configurations are pretty much the same as the example shown above.
At the beginning, I thought it was because the property inputWord
was not properly read in the query as a parameter, so I installed react-redux and pass the property as a global variable. However, I feel like that's not the point.
I'd appreciate any help or information about this problem.