【发布时间】:2021-06-11 09:15:23
【问题描述】:
我正在尝试使用 TypeORM 使用 Expo 从预填充的数据库中检索数据,模仿这个工作示例 (https://dev.to/jgabriel1/expo-sqlite-typeorm-4mn8)。它一直抛出这个错误;
undefined is not an object (evaluating 'ejRepository.getWordandMean')
at src/components/page/dictionarypage.js:32:28 in useCallback$argument_0
at src/components/page/dictionarypage.js:32:28 in useCallback$argument_0
at [native code]:null in callFunctionReturnFlushedQueue
更新
经过一些调查和编辑,我发现 dictionarypage.js 上的 ejRepository 未定义,而 connection.tsx 上的 context 返回一个空对象。我想知道为什么。
好像已经建立了连接。
这是我更新的代码
/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;
}
其他文件和配置与上面的示例几乎相同。
一开始我以为是因为inputWord这个属性在查询中没有被正确的读取为参数,所以我安装了react-redux,并将属性作为全局变量传递。但是,我觉得这不是重点。
如果能提供有关此问题的任何帮助或信息,我将不胜感激。
【问题讨论】:
标签: javascript typescript react-native expo typeorm