在SPFx WebPart中使用React useState报错求助
问题分析与解决方法
你的代码报错核心原因是违反了React Hook的使用规则:
useState是React Hook,只能在函数组件或自定义Hook的顶层作用域中调用,不能放在类组件外部,也不能在类组件的任何方法(包括构造函数)里使用。- 你把
useState定义在类组件外面,同时在类的构造函数里调用setNameOnCard,完全不符合Hook的使用逻辑,导致WebPart加载时出错。
下面给你两种可行的修正方案:
方案一:改用函数组件(推荐,符合React 17+最佳实践)
把类组件改成函数组件,在组件内部正确使用useState:
import * as React from 'react'; import styles from './PaymentForm.module.scss'; import type { IPaymentFormProps } from './IPaymentFormProps'; import { escape } from '@microsoft/sp-lodash-subset'; export default function PaymentForm(props: IPaymentFormProps): React.ReactElement<IPaymentFormProps> { // 在函数组件顶层调用useState const [nameOnCard, setNameOnCard] = React.useState("james"); const { description, isDarkTheme, environmentMessage, hasTeamsContext, userDisplayName } = props; return ( <section className={`${styles.paymentForm} ${hasTeamsContext ? styles.teams : ''}`}> {nameOnCard} <div className={styles.welcome}> <img alt="" src={isDarkTheme ? require('../assets/welcome-dark.png') : require('../assets/welcome-light.png')} className={styles.welcomeImage} /> <h2>Well done, {escape(userDisplayName)}!</h2> <div>{environmentMessage}</div> <div>Web part property value: <strong>{escape(description)}</strong></div> </div> <div> <h3>Welcome to SharePoint Framework!</h3> <p> The SharePoint Framework (SPFx) is a extensibility model for Microsoft Viva, Microsoft Teams and SharePoint. It's the easiest way to extend Microsoft 365 with automatic Single Sign On, automatic hosting and industry standard tooling. </p> <h4>Learn more about SPFx development:</h4> <ul className={styles.links}> <li><a href="https://aka.ms/spfx" target="_blank" rel="noreferrer">SharePoint Framework Overview</a></li> <li><a href="https://aka.ms/spfx-yeoman-graph" target="_blank" rel="noreferrer">Use Microsoft Graph in your solution</a></li> <li><a href="https://aka.ms/spfx-yeoman-teams" target="_blank" rel="noreferrer">Build for Microsoft Teams using SharePoint Framework</a></li> <li><a href="https://aka.ms/spfx-yeoman-viva" target="_blank" rel="noreferrer">Build for Microsoft Viva Connections using SharePoint Framework</a></li> <li><a href="https://aka.ms/spfx-yeoman-store" target="_blank" rel="noreferrer">Publish SharePoint Framework applications to the marketplace</a></li> <li><a href="https://aka.ms/spfx-yeoman-api" target="_blank" rel="noreferrer">SharePoint Framework API reference</a></li> <li><a href="https://aka.ms/m365pnp" target="_blank" rel="noreferrer">Microsoft 365 Developer Community</a></li> </ul> </div> </section> ); }
修改说明:
- 把类组件改为函数组件,直接接收
props参数 - 在函数组件的顶层作用域调用
useState,初始化值为"james" - 直接使用
props里的属性,不需要通过this.props访问
方案二:继续使用类组件(保留原有组件形态)
如果你想继续用类组件,就用React类组件的传统state方式,不要用Hook:
import * as React from 'react'; import styles from './PaymentForm.module.scss'; import type { IPaymentFormProps } from './IPaymentFormProps'; import { escape } from '@microsoft/sp-lodash-subset'; // 定义组件的state类型 interface IPaymentFormState { nameOnCard: string; } export default class PaymentForm extends React.Component<IPaymentFormProps, IPaymentFormState> { constructor(props: IPaymentFormProps) { super(props); // 初始化类组件的state this.state = { nameOnCard: "james" }; } public render(): React.ReactElement<IPaymentFormProps> { const { description, isDarkTheme, environmentMessage, hasTeamsContext, userDisplayName } = this.props; return ( <section className={`${styles.paymentForm} ${hasTeamsContext ? styles.teams : ''}`}> {/* 通过this.state访问state值 */} {this.state.nameOnCard} <div className={styles.welcome}> <img alt="" src={isDarkTheme ? require('../assets/welcome-dark.png') : require('../assets/welcome-light.png')} className={styles.welcomeImage} /> <h2>Well done, {escape(userDisplayName)}!</h2> <div>{environmentMessage}</div> <div>Web part property value: <strong>{escape(description)}</strong></div> </div> <div> <h3>Welcome to SharePoint Framework!</h3> <p> The SharePoint Framework (SPFx) is a extensibility model for Microsoft Viva, Microsoft Teams and SharePoint. It's the easiest way to extend Microsoft 365 with automatic Single Sign On, automatic hosting and industry standard tooling. </p> <h4>Learn more about SPFx development:</h4> <ul className={styles.links}> <li><a href="https://aka.ms/spfx" target="_blank" rel="noreferrer">SharePoint Framework Overview</a></li> <li><a href="https://aka.ms/spfx-yeoman-graph" target="_blank" rel="noreferrer">Use Microsoft Graph in your solution</a></li> <li><a href="https://aka.ms/spfx-yeoman-teams" target="_blank" rel="noreferrer">Build for Microsoft Teams using SharePoint Framework</a></li> <li><a href="https://aka.ms/spfx-yeoman-viva" target="_blank" rel="noreferrer">Build for Microsoft Viva Connections using SharePoint Framework</a></li> <li><a href="https://aka.ms/spfx-yeoman-store" target="_blank" rel="noreferrer">Publish SharePoint Framework applications to the marketplace</a></li> <li><a href="https://aka.ms/spfx-yeoman-api" target="_blank" rel="noreferrer">SharePoint Framework API reference</a></li> <li><a href="https://aka.ms/m365pnp" target="_blank" rel="noreferrer">Microsoft 365 Developer Community</a></li> </ul> </div> </section> ); } }
修改说明:
- 定义了组件的state类型
IPaymentFormState,规范state的结构 - 在构造函数里通过
this.state初始化值 - 在render里通过
this.state.nameOnCard访问状态值 - 如果后续需要修改这个值,要用
this.setState({ nameOnCard: "新值" }),不能直接修改state
内容的提问来源于stack exchange,提问作者user1231748
相关产品推荐
相关产品推荐

