Amir004
Amir004

Reputation: 19

SPFx + PnPjs: Upload failed – „context.pageContext is undefined“

I am developing an SPFx WebPart using PnPjs to upload files to a SharePoint document library.
However, when attempting to upload a file, I receive the following error:

Upload failed: TypeError: context.pageContext is undefined

Alternatively, I sometimes get a 403 error:

Upload failed: Error: Error making HttpClient request in queryable [403]  ::> {"odata.error":{"code":"-2147024891, System.UnauthorizedAccessException","message":{"lang":"de-DE","value":"Access Denied."}}}

I have checked whether context.pageContext is available by logging console.log(this.context), but it seems to be undefined. I also ensured that my PnPjs instance is initialized correctly using getSP(this.context) inside onInit(), and logging console.log(this.sp) confirms that a valid PnPJS instance is created. Additionally, I verified whether my user has write permissions for the SharePoint document library, as I suspect missing permissions could be causing the issue. However, I am unsure if a lack of permissions would specifically result in context.pageContext being undefined. I tested the WebPart both in the local workbench and in the online workbench (https://aivdev.sharepoint.com/%5C_layouts/15/workbench.aspx), but the issue persists in both environments.

Why is context.pageContext undefined?

ProgressReportWebPart.ts

import * as React from 'react';
import * as ReactDom from 'react-dom';
import { BaseClientSideWebPart } from '@microsoft/sp-webpart-base';
import { IProgressReportProps } from './components/IProgressReportProps';
import ProgressReport from './components/ProgressReport';
import { getSP } from '../../pnpjsConfig';
import { SPFI } from "@pnp/sp";

export default class ProgressReportWebPart extends BaseClientSideWebPart<IProgressReportProps> {
  private sp: SPFI;

  public render(): void {
    const element: React.ReactElement<IProgressReportProps> = React.createElement(
      ProgressReport,
      {
        context: this.context // 🔹 Passing the context
      }
    );

    ReactDom.render(element, this.domElement);
  }

  public async onInit(): Promise<void> {
    await super.onInit();
    this.sp = getSP(this.context);
  }
}

ProgressReport.tsx

import * as React from "react";
import { WebPartContext } from "@microsoft/sp-webpart-base";
import PnpFileUpload from "./PnpFileUpload";

export interface IProgressReportProps {
  context: WebPartContext;
}

const ProgressReport: React.FC<IProgressReportProps> = ({ context }) => {
  return (
    <div>
      <h1>📊 Progress Report</h1>
      <PnpFileUpload context={context} />
    </div>
  );
};

export default ProgressReport;

PnpFileUpload.tsx:

import * as React from "react";
import { WebPartContext } from "@microsoft/sp-webpart-base";
import { SPFI } from "@pnp/sp";
import "@pnp/sp/files";
import "@pnp/sp/folders";
import { getSP } from "../../../pnpjsConfig";

export interface IPnpFileUploadProps {
  context: WebPartContext;
}

export interface IPnpFileUploadState {
  selectedFile: File | null;
}

export default class PnpFileUpload extends React.Component<IPnpFileUploadProps, IPnpFileUploadState> {
  private sp: SPFI;

  constructor(props: IPnpFileUploadProps) {
    super(props);
    this.sp = getSP(props.context);

    this.state = {
      selectedFile: null,
    };

    this.handleFileChange = this.handleFileChange.bind(this);
    this.filesave = this.filesave.bind(this);
  }

  handleFileChange(event: React.ChangeEvent<HTMLInputElement>) {
    const file = event.target.files?.[0] || null;
    this.setState({ selectedFile: file });
  }

  async filesave() {
    const { selectedFile } = this.state;
    if (!selectedFile) {
      console.log("No file selected");
      return;
    }

    try {
      const folderUrl = "/sites/aivdev/ProgressReport";

      const fileAddResult = await this.sp.web.getFolderByServerRelativePath(folderUrl)
        .files.addUsingPath(selectedFile.name, selectedFile, { Overwrite: true });

      console.log("File Uploaded:", fileAddResult);
    } catch (error) {
      console.error("Upload failed:", error);
    }
  }

  public render(): React.ReactElement<IPnpFileUploadProps> {
    return (
      <div>
        <input type="file" onChange={this.handleFileChange} />
        <button onClick={this.filesave}>Upload File</button>
      </div>
    );
  }
}

Upvotes: 0

Views: 25

Answers (0)

Related Questions