Pnpjs: getNext 'parent is undefined'

Created on 27 Nov 2018  路  6Comments  路  Source: pnp/pnpjs

Category

  • [ ] Enhancement
  • [x] Bug
  • [ ] Question
  • [ ] Documentation gap/issue

Version

Please specify what version of the library you are using: [1.2.6]

Please specify what version(s) of SharePoint you are targeting: [spfx 1.6.0 (online)]

Expected / Desired Behavior / Question

A PagedItemCollection is returned (or null).

Observed Behavior

Calling getNext() on a PagedItemCollection does not succeed - The following error is caught: TypeError: "parent is undefined". I believe the error is coming from here.

Steps to Reproduce

I'm not entirely sure, however I have a feeling this is related to context being lost when page collection objects are passed around.

This is my code which causes the error:

let post: IBaseFeedItem = this._feed.filter(f => f.id == replyToId)[0];
let nextPage = await post.page.getNext();

post.page is definitely defined, of type PagedItemCollection<any[]> and has all 3 of the expected getNext, hasNext and results values stored on it.

code by design question

All 6 comments

Hi @JakeStanger - from your code we can't really see what you are doing with the library. Is there a chance you can provide a minimal reproduction of the issue we can clone and look at?

I've managed to get my code working - there's too much going on to reasonably show. I believe I've found the problem, which lies with destructuring the page response.

This works fine:

let page = await doSomePagedRequest();
let someObject {someProp: "Something", page: page};
someObject.page.getNext();

This also works fine:

let page = await doSomePagedRequest();
let someObject {someProp: "Something", results: page.results, hasNext: page.hasNext};
console.log(someObject.results, someObject.hasNext);

This calls a valid function, but prints null:

let page = await doSomePagedRequest();
let someObject {someProp: "Something", getNext: page.getNext};
console.log(someObject.getNext());

It appears some form of context is lost with getNext.

Oh, so you were not using the object we return but trying to take just a few parts of that? Yes, that fairly clearly won't work and isn't supported. Going to close this as by design.

That seems like a fairly unstandard design and should probably be documented more clearly. Taking only what is necessary from an object is a common design pattern for obvious reasons, and it is not made clear that taking the callback function and calling it from outside of the object would cause issues.

I understand if there are technical reasons as to why it must be kept inside the object, but passing callbacks around is far from non-standard so if this is the case it should be made clear.

No, destructuring data objects is fine as they are usually plain objects. You are likely thinking of props in React which commonly uses this pattern.

A class instance contains both data and functionality and the idea that you should be able to just pick pieces off that is simply wrong. That would require anyone writing a class you are consuming to incorporate ALL information within the class into each method and property. Classes have properties (public/private) and methods (public/private) that can refer to properties or other methods within that class - or inherited members. Each of those methods in your interpretation would need to encapsulate ALL of the other properties and methods of the class instance within itself. Even a property described with a getter could reference other information within the class and fail if removed from that context.

Consider the below example:

class ObjectExample {

    constructor(private _value: string) { }

    public getValue(): string {
        return this._value;
    }
}

const instance = new ObjectExample("My Value");

const { getValue } = instance;

// this throws (node:28876) UnhandledPromiseRejectionWarning: TypeError: Cannot read property '_value' of undefined
console.log(getValue());

You are right, my apologies. I was treating the response like an object typed to an interface, rather than a class. I was caught out by the fact Typescript let me do that at all. Cheers.

Was this page helpful?
0 / 5 - 0 ratings