简体   繁体   English

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

[英]React (typescript): How to loop inside const creation

Beginner React/Typescript learner here, I am trying to improve this class I have:初学者 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;

particularly this part:特别是这部分:

      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}
      },

This section seems like it could easily be looped over a const [] with month names.这部分似乎可以很容易地在带有月份名称的 const [] 上循环。 But I can't seem to find any reference on how to achieve it.但我似乎找不到任何关于如何实现它的参考。

Any help or point to a reference example would be greatly appreciated!任何帮助或指向参考示例将不胜感激!

You can use Object.values , Object.keys or Object.entries .您可以使用Object.valuesObject.keysObject.entries

Object.values(fields).map(month => <Field {...month}/>)

If you want to separate the months, you can split the array in half ( Object.values(fields) ) and render both separately.如果你想分开月份,你可以将数组分成两半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>
        ...
    )

}

Edit:编辑:

Instead of having that huge object and supposing all the properties are the same except for the name, here is something you can do with .reduce (you could also do with a .forEach )相反,具有巨大的物体,并假定所有属性相同,只是名称相同的,这里是你可以用做.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
}, {})

And with this, you will have created that huge object有了这个,你就创建了那个巨大的对象

Combining both thins, here is what you can do结合这两种方法,这是你可以做的

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

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

If I understand correctly, you are thinking about refactoring the creation of a list of objects by looping over a list of month names.如果我理解正确,您正在考虑通过遍历月份名称列表来重构对象列表的创建。 Vencovsky shows how to use reduce() to do this. Vencovsky 展示了如何使用reduce()来做到这一点。 I would go a step further and create the <Field> components directly by using map() :我会更进一步,使用map()直接创建<Field>组件:

const months = ['Jan', 'Feb', 'Mar', /* ...rest */] 
const monthFields = months.map(m => 
   <Field id={m}
      label={m}
      editor="dropdown"
      options={data}
      value="hello"
      validation={{rule: required}} />
);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM