【问题标题】:React (typescript): How to loop inside const creationReact(打字稿):如何在 const 创建中循环
【发布时间】:2019-12-06 18:34:09
【问题描述】:

这里是 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;

尤其是这部分:

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

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

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

【问题讨论】:

    标签: javascript reactjs typescript


    【解决方案1】:

    您可以使用Object.valuesObject.keysObject.entries

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

    如果你想分开月份,你可以split the array in half (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>
            ...
        )
    
    }
    

    编辑:

    不要拥有那个巨大的对象并假设除了名称之外所有属性都相同,这是您可以使用.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
    }, {})
    

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

    结合两者,这就是你可以做的事情

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

    【讨论】:

    • Object.entries(为了完整性)
    • 谢谢,您对如何循环const fields: IFields = {...} 部分(第二个代码块)有任何提示吗?如果我理解正确,那只是一个数组,但我想在循环中插入它,而不是声明整个东西大部分都是用不同的键重复的,谢谢!
    • @tom 我不明白你想要什么。您想要一个带有月份名称的数组并创建那个巨大的字段对象吗?
    • @tom 检查我的编辑,也许这就是你需要的,请告诉我我的假设是否正确。
    • @Vencovsky 是的,没错,我会有一个let month = ["jan", "feb", "mar"] 并在上面做一个month.map(...),理想情况下我可以在这个循环中创建那个巨大的fields 对象
    【解决方案2】:

    如果我理解正确,您正在考虑通过循环月份名称列表来重构对象列表的创建。 Vencovsky 展示了如何使用reduce() 来执行此操作。我会更进一步,使用map() 直接创建&lt;Field&gt; 组件:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-07-27
      • 2019-09-24
      • 2022-11-02
      • 1970-01-01
      • 2019-06-21
      • 2019-10-22
      • 1970-01-01
      相关资源
      最近更新 更多