【问题标题】:TypeError: undefined is not an object (evaluating 'ejRepository.getWordandMean')类型错误:未定义不是对象(评估'ejRepository.getWordandMean')
【发布时间】: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


    【解决方案1】:

    一个可能的问题是您已将 inputWord 声明为对象和该对象中的键,这可能会导致冲突。尝试更改 repository.ts 中的以下函数:

    public async getWordandMean(inputWord:{inputWord: String}): Promise<EJmodel> {
    const results: EJmodel = await this.ormRepository.query('select * from items where word like ?;',[inputWord],
    );
      return results; 
    }
    

    到:

    public async getWordandMean(obj:{inputWord: String}): Promise<EJmodel> {
    const results: EJmodel = await this.ormRepository.query('select * from items where word like ?;',obj.inputWord,
    );
      return results;
    }
    

    【讨论】:

    • 感谢您的回复!我尝试了您建议的代码,但它引发错误“绑定元素'inputWord'隐式具有'任何'类型”。
    • @mak.skid - 更新了“to:”下方的代码。试试看,我认为它应该可以工作。
    • 看起来很有希望,但它仍然不起作用:(
    猜你喜欢
    • 2020-04-02
    • 2023-03-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-22
    • 2021-10-21
    • 1970-01-01
    相关资源
    最近更新 更多