joethemow
joethemow

Reputation: 1773

Why is my Many to Many relationship field undefined?

I am trying to create a follower/following system and when I try to append the new user to the following list I get the error Cannot read property 'push' of undefined. This ends up creating 2 separate tables one for users following other users and one for users being followed by other users. Not sure why it's not picking up the field? Any help is appreciated.

import { Length } from "class-validator";
import {
    Column,
    CreateDateColumn,
    Entity,
    JoinTable,
    ManyToMany,
    OneToMany,
    PrimaryColumn,
    RelationCount,
    Unique,
    UpdateDateColumn
} from "typeorm";

export class User {

    @PrimaryColumn()
    public user_id: string;

    @Column()
    public first_name: string;

    @Column()
    public last_name: string;

    @Column()
    public email: string;

    @Column()
    public phone_number: string;

    @Column()
    public username: string;

    @Column()
    @CreateDateColumn()
    public created_on: Date;

    @Column()
    @UpdateDateColumn()
    public updated_at: Date;

    @ManyToMany((type) => User, (user) => user.following)
    @JoinTable()
    public followers: User[];

    @ManyToMany((type) => User, (user) => user.followers)
    @JoinTable()
    public following: User[];

    @RelationCount((user: User) => user.followers)
    public followers_count: number;

    @RelationCount((user: User) => user.following)
    public following_count: number;
}

const { user_id, 
        follow_user_id } = req.
const user_repo = getRepository(User);
const user = await user_repo.findOne({
    where: {user_id}
});
const follow_user = new User();

follow_user.user_id = follow_user_id;
user.following.push(follow_user);
const result = user_repo.save(user);

Error is referring to this line user.following.push(follow_user);

UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'push' of undefined

Upvotes: 4

Views: 4190

Answers (3)

Tom Baldwin
Tom Baldwin

Reputation: 29

We use this approach to avoid undefined lists:

@ManyToMany((type) => User, (user) => user.following)
@JoinTable()
private _followers: User[];

...

get followers() : User[] {
  if (!_followers) {
    _followers = [];
  }
  return _followers;
}

Upvotes: 1

Noah Anderson
Noah Anderson

Reputation: 1191

I encountered a similar error with OneToMany and ManyToOne relations where the relative returned null/undefined.

The workaround I'm using involves putting this in the User class:

  @AfterLoad()
  async nullChecks() {
    if (!this.followers) {
      this.followers = []
    }

    if (!this.following) {
      this.following = []
    }
  }

documentation

Upvotes: 7

cxↄ
cxↄ

Reputation: 1358

I didn't test ways below, but think one of them should help you.

1st way. At your User class.

    // Source code omission
    @ManyToMany((type) => User, (user) => user.followers)
    @JoinTable()
    public following: User[] = []; // ★ Added assign
    // Source code omission

2nd way. At your User class.

export class User {
    // Source code omission
    constructor() { // ★ Added line
        this.following = []; // ★ Added line
    } // ★ Added line
}

3rd way. At place where you use User class.

const follow_user = new User();

follow_user.user_id = follow_user_id;
user.following = []; // ★ Added line
user.following.push(follow_user);
const result = user_repo.save(user);

4th way. At place where you use User class.

const follow_user = new User();

follow_user.user_id = follow_user_id;
user.following = [follow_user]; // ★ Edited line
const result = user_repo.save(user);

Upvotes: 3

Related Questions