所以我有这个反应组件,下拉属性(SPFx)有2个值,我需要在下拉列表更改时再次重新生成react,下拉列表定义从哪里检索值的数据源
Webpart.ts
import * as React from 'react';
import * as ReactDom from 'react-dom';
import { Version } from '@microsoft/sp-core-library';
import {
BaseClientSideWebPart,
IPropertyPaneConfiguration,
PropertyPaneDropdown
} from "@microsoft/sp-webpart-base";
import * as strings from 'AbstractfactoryWebPartStrings';
import Abstractfactory from './components/Abstractfactory';
import { IAbstractFactoryProps } from './components/IAbstractFactoryProps';
import { IAbstractfactoryWebPartProps } from "./IAbstractfactoryWebPartProps";
export default class AbstractfactoryWebPart extends BaseClientSideWebPart<IAbstractfactoryWebPartProps> {
public render(): void {
const element: React.ReactElement<IAbstractFactoryProps > = React.createElement(
Abstractfactory,
{
datasource: this.properties.datasource
}
);
ReactDom.render(element, this.domElement);
}
protected get dataVersion(): Version {
return Version.parse('1.0');
}
protected onPropertyPaneFieldChanged(propertyPath: string, oldValue: any, newValue: any): void {
super.onPropertyPaneFieldChanged(propertyPath, oldValue, newValue);
}
protected getPropertyPaneConfiguration(): IPropertyPaneConfiguration {
return {
pages: [
{
header: {
description: strings.PropertyPaneDescription
},
groups: [
{
groupName: strings.BasicGroupName,
groupFields: [
PropertyPaneDropdown("datasource", {
label: "DataSource",
options: [
{ key: "1", text: "Sharepoint"},
{ key: "2", text: "JSON" }
],
selectedKey: "1",
})
]
}
]
}
]
};
}
}
Component.tsx
import * as React from 'react';
import { IAbstractFactoryProps } from "./IAbstractFactoryProps";
import { IAbstractFactoryState } from "./IAbstractFactoryState";
import styles from './Abstractfactory.module.scss';
import { escape } from '@microsoft/sp-lodash-subset';
import DaoFactory from "./DaoFactory";
import ICustomerDao from "./ICustomerDao";
import DataSources from "./DatasourcesEnum";
export default class Abstractfactory extends React.Component<IAbstractFactoryProps, IAbstractFactoryState> {
//Private instance of customerDao, please note it returns ICustomerDao, an Interface,
//not a concrete type
private customerDao: ICustomerDao;
constructor(props: IAbstractFactoryProps, state: IAbstractFactoryState) {
super(props);
this.setInitialState();
// We set the Dao depending on the selected data source
this.setDaos(props.datasource);
//Then we set the list of customers and note, we dont care if they come from Sharepoint
//Rest API or anything else.
this.state = {
items: this.customerDao.listCustomers(),
};
}
public render(): React.ReactElement<IAbstractFactoryProps> {
return (
<div className={ styles.abstractfactory }>
<div className={ styles.container }>
<div className={ styles.row }>
<div className={ styles.column }>
{this.state.items.map( i => (<div key={i.id}>{i.firstName}</div>))}
</div>
</div>
</div>
</div>
);
}
public setInitialState(): void {
this.state = {
items: []
};
}
private setDaos(datasource: string): void {
const data: DataSources = datasource === "Sharepoint" ? DataSources.SharepointList : DataSources.JsonData;
this.customerDao = DaoFactory.getDAOFactory(data).getCustomerDAO();
//Now, its transparent for us a UI developers what datasource was selected
//this.customerDao.
}
}
国家
import Customer from "./Customer";
export interface IAbstractFactoryState {
items?: Customer[];
}
DaoFactory
import ICustomerDAO from "./ICustomerDAO";
import DataSources from "./DatasourcesEnum";
abstract class DAOFactory {
//For each entity we will need to implement getCustomerDAO, this will make it easily replaceable
//when another datasource comes in
public abstract getCustomerDAO(): ICustomerDAO;
//Static method that receives a parameter depending on the datasource and will return the specifc
//factory
public static getDAOFactory(whichFactory: DataSources): DAOFactory {
switch (whichFactory) {
case DataSources.SharepointList:
return new SharepointListDAOFactory();
case DataSources.JsonData:
return new JsonDAOFactory();
default :
return null;
}
}
}
export default DAOFactory;
import SharepointListDAOFactory from "./SharepointListDAOFactory";
import JsonDAOFactory from "./JsonDAOFactory";
JsonCustomerDao.ts
import ICustomerDao from "./ICustomerDao";
import Customer from "./Customer";
class JsonCustomerDAO implements ICustomerDao{
public insertCustomer(): number {
// implementation to be done by reader
return 1;
}
public deleteCustomer(): boolean {
// implementation to be done by reader
return true;
}
public findCustomer(): Customer {
// implementation to be done by reader
return new Customer();
}
public updateCustomer(): boolean {
// implementation to be done by reader
return true;
}
public listCustomers(): Customer[] {
// implementation to be done by reader
let c1: Customer= new Customer();
let c2: Customer= new Customer();
c1.id="3";
c1.firstName="Andrew";
c1.lastName="Valencia";
c2.id="4";
c2.firstName="Charles";
c2.lastName="Smith";
let list: Array<Customer> = [c1, c2 ];
return list;
}
}
export default JsonCustomerDAO;
SharepointCustomerDao
import ICustomerDao from "./ICustomerDao";
import Customer from "./Customer";
class SharepointCustomerDao implements ICustomerDao {
public insertCustomer(): number {
// implementation to be done by reader
return 1;
}
public deleteCustomer(): boolean {
// implementation to be done by reader
return true;
}
public findCustomer(): Customer {
// implementation to be done by reader
return new Customer();
}
public updateCustomer(): boolean {
// implementation to be done by reader
return true;
}
public listCustomers(): Customer[] {
// implementation to be done by reader
let c1: Customer = new Customer();
c1.id="1";
c1.firstName="Luis";
c1.lastName="Valencia";
let c2: Customer = new Customer();
c2.id="2";
c2.firstName="John";
c2.lastName="Smith";
let list: Array<Customer> = [c1, c2 ];
return list;
}
}
export default SharepointCustomerDao;
第一次执行为默认数据源呈现的值,但是当属性更改时,UI不会随新值一起更改。
我发现我可以使用此事件在下拉列表更改时设置新的道具数据源值
protected onPropertyPaneFieldChanged(propertyPath: string, oldValue: any, newValue: any): void {
this.properties[this.properties.datasource] = newValue;
this.render();
super.onPropertyPaneFieldChanged(propertyPath, oldValue, newValue);
}
但是视图没有重新渲染,我可以使用任何react js事件来重新渲染或重新设置prop更改时的状态吗?
答案 0 :(得分:1)
Reacts在数据更改时重新呈现组件的方法是更新它的状态。
例如,如果你有一个组件<Foo />
,其中包含一个rendermethod来显示它的状态
...
render() {
return(
<div>Hello {this.state.name}</div>
)
}
...
组件将显示Hello ,并且whetever位于state.name
中每次更新给定组件的状态时都会重新渲染。因此,在您的情况下,如果您获得新项目,则必须将其推入州。一旦发生这种情况,react类将触发其render方法,并将使用当前状态显示新数据。
为了实现这一点,您需要一个从外部或组件内部调用的自定义方法。
例如
...
foo(receivesSomething) {
const items = this.state.items;
items.push(receivesSomething);
this.setState({items}); // once a setState is being executed in any component react will make a diff between the current DOM and the ShadowDOM, if something is different then it will trigger a re-render of the affected component
}
...
这篇文章编写得很好http://lucybain.com/blog/2017/react-js-when-to-rerender/并对其进行了解释。我建议你一般来看一下生命周期方法。
<强>更新强>
例如像这样。
class Foo extends React.Component {
constructor(props){
super();
window.someFunction = payload => {
// do whatever you want to do with the payload here
this.setState({ items: payload });
}
}
}
<强> UPDATE2 强>
如果您的组件正在侦听/接收道具,您可以使用componentWillReceiveProps(newProps)
生命周期方法做出反应并更新其中的组件状态