在React组件中呈现多个项目

8
我正在实现抽象工厂模式,getitems 方法能够正常工作并返回了 2 个我模拟的项目,但是我不确定如何在 React 组件中渲染这些项目。
以下是我的代码:
AbstractFactory.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, {}> {
  private customerDao: ICustomerDao;

    constructor(props: IAbstractFactoryProps, state: IAbstractFactoryState) {
      super(props);
      this.setInitialState();
      this.setDaos(props.datasource);

      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}
               </div>
            </div>
          </div>
        </div>
      )
    }

    public setInitialState(): void {
      this.state = {
        items: []
      };
    }

    private setDaos(datasource: string): void {
      const data: any = 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.
    }
}

Customer.ts

class Customer{  
    public id: string;
    public firstName: string;
    public lastName: string;
}

export default Customer;

Datasourcesenum.ts

enum DataSources {  
    SharepointList = "SharepointList",
    JsonData = "JsonData"
}

export default DataSources;

DaoFactory.ts

import ICustomerDAO from "./ICustomerDAO";  

import DataSources from "./DatasourcesEnum";

abstract class DAOFactory {

    public abstract getCustomerDAO(): ICustomerDAO;

    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";  

JsonDaoFactory.ts

import DAOFactory from "./DaoFactory";  
import JsonCustomerDAO from "./JsonCustomerDAO";
import ICustomerDao from "./ICustomerDao";

class JsonDAOFactory extends DAOFactory {  
    public getCustomerDAO(): ICustomerDao{
        return new JsonCustomerDAO();
    }
}

export default JsonDAOFactory; 

SharepointListDaoFactory.ts

import DaoFactory from "./DaoFactory";  
import ICustomerDao from "./ICustomerDao";  
import SharepointCustomerDao from "./SharepointCustomerDAO";

class SharepointListDAOFactory extends DaoFactory {  
    public getCustomerDAO(): ICustomerDao{
        return new SharepointCustomerDao();
    }
}

export default SharepointListDAOFactory;

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.ts

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;

Icustomerdao

import Customer from "./Customer";

 interface ICustomerDao {
    insertCustomer(): number;
    deleteCustomer(): boolean;
    findCustomer(): Customer;
    updateCustomer(): boolean;
    listCustomers(): Customer[];
}

export default ICustomerDao;

.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, {}> {
  private customerDao: ICustomerDao;

    constructor(props: IAbstractfactoryProps, state: IAbstractFactoryState) {
      super(props);
      this.setInitialState();
      this.setDaos(props.datasource);
    }

    public render(): React.ReactElement<IAbstractfactoryProps> {
      this.state = {
          items: this.customerDao.listCustomers(),
      };

      return null;
    }

    public setInitialState(): void {
      this.state = {
        items: []
      };
    }

    private setDaos(datasource: string): void {
      const data: any = datasource === "Sharepoint" ? DataSources.SharepointList : DataSources.JsonData;
      this.customerDao = DaoFactory.getDAOFactory(data).getCustomerDAO();
    }
}

更新1

我将渲染方法更改如下:

 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>i.id</div>)}
               </div>
            </div>
          </div>
        </div>
      );
    }

我有以下两个问题:

[23:11:06] Error - typescript - src/webparts/abstractfactory/components/Abstractfactory.tsx(34,63): error TS1005: ',' expected.
[23:11:06] Error - typescript - src/webparts/abstractfactory/components/Abstractfactory.tsx(34,30): error TS2339: Property 'items' does not exist on type 'Readonly<{}>'.

1
你从哪里得到的这样编写React代码的想法?这段代码比必要的复杂度高了几个数量级。 - azium
你为什么认为这很复杂?对我来说很容易理解。 - Luis Valencia
其实我也感到困惑了。可能是因为代码量太大了。那么你想要渲染什么,以及你想如何进行渲染呢?你期待什么输出结果?对于我来说,由于代码太多,很难理解。 - Leo Odishvili
我想在Chrome调试器中呈现2个客户的ID、名字和姓氏,我可以看到对象已经填充,但由于我不是React专家,我不知道如何将对象数组呈现为一个漂亮的表格。 - Luis Valencia
请记住,您正在使用React,而不是Java/C#。不要过度复杂化您的代码。 - Naramsim
显示剩余4条评论
2个回答

4

**更新** 好的,那么我们将保留listCustomers方法。

根据您的代码和渲染方法的内容,items等于客户数组,对吗? 如果是这样,请进行替换。

{this.state.items}

使用

{this.state.items.map( i => (<div>i.id</div>)}

例如。
顺便提一句:当React的状态改变时,它会重新渲染组件。因此,每当您更新customerList时,请确保将其放在呈现它们的组件的状态中。

我刚刚发布了包含渲染方法的.tsx文件。你的做法并没有让我信服,因为我认为它违反了单一职责原则,通过将HTML添加到返回值中。 - Luis Valencia
将HTML添加到返回值中违反了单一职责原则,您是什么意思?渲染函数的整个想法是我们想要将HTML元素或React组件呈现到DOM中。 - Komolafe Tolulope
@KomolafeTolulope 每个类应该只有一个单一的职责,检查SOLID原则,所以TSX可以渲染HTML,但Dao类应该只返回数据而不是渲染HTML,渲染逻辑应该在组件中完成。 - Luis Valencia
@noa-de v 请查看我的更新!有语法错误。 - Luis Valencia
1
@LuisValencia 这些只是 TSC 错误,对吧?代码本身是可以工作的?很重要要知道 :) - noa-dev
显示剩余2条评论

1
如果您想使用自定义jsx渲染多个组件,可以创建一个接收对象并返回jsx的函数,例如:
const myCustomer =({id,name,phone}){
  //Do stuff here
  return(<div><span>{name}</span><span>{phone}</span></div>)
}

然后在你的组件中,你可以这样在渲染时调用它:

items.map((customer,i)=> <myCustomer key={i} {...customer}/>)

注意:如果您需要为每一行保留状态,可以使用React.Component而不是函数。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接