React(打字稿):如何在常量创建中循环

tom*_*tom 4 javascript typescript reactjs

初学者 React/Typescript 学习者在这里,我正在努力改进我拥有的这门课:

import * as React from 'react';
import {Form, IFields, isEmail, required} from "../../components/Form";
import {Field} from "../../components/Field";

const API = '/api/getmonth';

export interface Props {
}

interface State {
  data: string[],
  isLoading: boolean,
  error: any,
}

class monthForm extends React.Component<Props, State> {
  constructor(props: Props) {
    super(props);

    this.state = {
      data: [],
      isLoading: false,
      error: null,
    };
  }


  componentDidMount() {
    this.setState({isLoading: true});

    fetch(API)
      .then(response => {
        if (response.ok) {
          return response.json();
        } else {
          throw new Error('Error getting month list');
        }
      })
      .then(content => this.setState({data: content, isLoading: false}))
      .catch(error => this.setState({error, isLoading: false}));
  }

  render() {
    const {data, isLoading, error} = this.state;

    if (error) {
      return <p>{error.message}</p>;
    }
    if (isLoading) {
      return (
        <p>Loading ...</p>
      )
    }

    const fields: IFields = {
      jan: {
        id: "jan",
        label: "Jan",
        editor: "dropdown",
        options: data,
        value: "hello",
        validation: {rule: required}
      },
      feb: {
        id: "feb",
        label: "Feb",
        editor: "dropdown",
        options: data,
        value: "hello",
        validation: {rule: required}
      },
      mar: {
        id: "mar",
        label: "Mar",
        editor: "dropdown",
        options: data,
        value: "hello",
        validation: {rule: required}
      },
      apr: {
        id: "apr",
        label: "Apr",
        editor: "dropdown",
        options: data,
        value: "hello",
        validation: {rule: required}
      },
      may: {
        id: "may",
        label: "May",
        editor: "dropdown",
        options: data,
        value: "hello",
        validation: {rule: required}
      },
      jun: {
        id: "jun",
        label: "Jun",
        editor: "dropdown",
        options: data,
        value: "hello",
        validation: {rule: required}
      },
      jul: {
        id: "jul",
        label: "Jul",
        editor: "dropdown",
        options: data,
        value: "hello",
        validation: {rule: required}
      },
      aug: {
        id: "aug",
        label: "Aug",
        editor: "dropdown",
        options: data,
        value: "hello",
        validation: {rule: required}
      },
      sep: {
        id: "sep",
        label: "Sep",
        editor: "dropdown",
        options: data,
        value: "hello",
        validation: {rule: required}
      },
      oct: {
        id: "oct",
        label: "Oct",
        editor: "dropdown",
        options: data,
        value: "hello",
        validation: {rule: required}
      },
      nov: {
        id: "nov",
        label: "Nov",
        editor: "dropdown",
        options: data,
        value: "hello",
        validation: {rule: required}
      },
      dec: {
        id: "dec",
        label: "Dec",
        editor: "dropdown",
        options: data,
        value: "hello",
        validation: {rule: required}
      },
    };
    return (
      <Form
        action="/react/test/form"
        fields={fields}
        render={() => (
          <React.Fragment>
            <div className="alert alert-info" role="alert">
              Select Projection for each month
            </div>
            <div className="container">
              <div className="row">
                <div className="col-md-3">
                  <Field {...fields.jan}/>
                  <Field {...fields.feb}/>
                  <Field {...fields.mar}/>
                  <Field {...fields.apr}/>
                  <Field {...fields.may}/>
                  <Field {...fields.jun}/>
                </div>
                <div className="col-md-3">
                  <Field {...fields.jul}/>
                  <Field {...fields.aug}/>
                  <Field {...fields.sep}/>
                  <Field {...fields.oct}/>
                  <Field {...fields.nov}/>
                  <Field {...fields.dec}/>
                </div>
              </div>
            </div>
          </React.Fragment>
        )}
      />
    );
  }
}

export default monthForm;
Run Code Online (Sandbox Code Playgroud)

特别是这部分:

      jan: {
        id: "jan",
        label: "Jan",
        editor: "dropdown",
        options: data,
        value: "hello",
        validation: {rule: required}
      },
      feb: {
        id: "feb",
        label: "Feb",
        editor: "dropdown",
        options: data,
        value: "hello",
        validation: {rule: required}
      },
      mar: {
        id: "mar",
        label: "Mar",
        editor: "dropdown",
        options: data,
        value: "hello",
        validation: {rule: required}
      },
      apr: {
        id: "apr",
        label: "Apr",
        editor: "dropdown",
        options: data,
        value: "hello",
        validation: {rule: required}
      },
      may: {
        id: "may",
        label: "May",
        editor: "dropdown",
        options: data,
        value: "hello",
        validation: {rule: required}
      },
Run Code Online (Sandbox Code Playgroud)

这部分似乎可以很容易地在带有月份名称的 const [] 上循环。但我似乎找不到任何关于如何实现它的参考。

任何帮助或指向参考示例将不胜感激!

Ven*_*sky 5

您可以使用Object.values,Object.keysObject.entries

Object.values(fields).map(month => <Field {...month}/>)
Run Code Online (Sandbox Code Playgroud)

如果要分隔月份,可以将数组一分为二( Object.values(fields)) 并分别渲染。

render(){
    const months = Object.values(fields)
    const halfwayThrough = Math.floor(months.length / 2)
    const monthFirstHalf = months.slice(0, halfwayThrough);
    const monthSecondHalf = months.slice(halfwayThrough, months.length);

    ...

    return (
        ...
        <div className="col-md-3">
            {monthFirstHalf.map(month => <Field {...month}/>)}
        </div>
        <div className="col-md-3">
            {monthSecondHalf.map(month => <Field {...month}/>)}
        </div>
        ...
    )

}
Run Code Online (Sandbox Code Playgroud)

编辑:

与其拥有那个巨大的对象并假设除名称之外的所有属性都相同,不如您可以使用以下方法.reduce(您也可以使用.forEach

const months = ['Jan', 'Feb', 'Mar', /* ...rest */] 
const fields = months.reduce((monthObject, monthName) => {
    let monthId = monthName.toLowerCase()
    monthObject[monthId] = {
        id: monthId,
        label: monthName,
        editor: "dropdown",
        options: data,
        value: "hello",
        validation: {rule: required}
    }
    return monthObject
}, {})
Run Code Online (Sandbox Code Playgroud)

有了这个,你就创建了那个巨大的对象

结合这两种方法,这是你可以做的

const months = ['Jan', 'Feb', 'Mar', /* ...rest */] 

return (
   ...
   {months.map(month => <Field 
           id={month}
           label={month}
           editor: "dropdown",
           options: data,
           value: "hello",
           validation: {rule: required}
       />
   )}
   ...
)
Run Code Online (Sandbox Code Playgroud)