javascript - React.js - Create input elements from JSON schema - Stack Overflow

I'm looking for advice on the best way to dynamically create elements from JSON in React using map

I'm looking for advice on the best way to dynamically create elements from JSON in React using mapping with ponents.

I figure we can have each input type as a separate ponent class and construct the element passing in props and bind the changes.

E.g. the JSON:

    {
        "type": "text",
        "name": "FirstName",                    
        "class": "text",
        "placeholder": "Enter first name"
    },
    {
        "type": "text",
        "name": "Surname",                  
        "class": "text",
        "placeholder": "Enter surname"
    },

React:

class InputText extends React.Component {
  constructor(props) {
    super(props);
    this.changeValue = this.changeValue.bind(this);
  }

  render() {
    return (
      <div className={className}>
        <label htmlFor={this.props.name}>{this.props.title}</label>
        <input
          onChange={this.changeValue}
          name={this.props.name}
          type={this.props.type}
          value={this.props.value}
        />
      </div>
    );
  }
}

Any advice on the best way to iterate through (and validate) each item in the JSON? Am I on the right track here? Thanks!

I'm looking for advice on the best way to dynamically create elements from JSON in React using mapping with ponents.

I figure we can have each input type as a separate ponent class and construct the element passing in props and bind the changes.

E.g. the JSON:

    {
        "type": "text",
        "name": "FirstName",                    
        "class": "text",
        "placeholder": "Enter first name"
    },
    {
        "type": "text",
        "name": "Surname",                  
        "class": "text",
        "placeholder": "Enter surname"
    },

React:

class InputText extends React.Component {
  constructor(props) {
    super(props);
    this.changeValue = this.changeValue.bind(this);
  }

  render() {
    return (
      <div className={className}>
        <label htmlFor={this.props.name}>{this.props.title}</label>
        <input
          onChange={this.changeValue}
          name={this.props.name}
          type={this.props.type}
          value={this.props.value}
        />
      </div>
    );
  }
}

Any advice on the best way to iterate through (and validate) each item in the JSON? Am I on the right track here? Thanks!

Share Improve this question edited Dec 10, 2017 at 17:39 Paul Redmond asked Dec 10, 2017 at 15:19 Paul RedmondPaul Redmond 3,2964 gold badges35 silver badges53 bronze badges
Add a ment  | 

3 Answers 3

Reset to default 2

You need a ponent that maps over the data and returns the collection of InputTexts. Here I've called it Main.

class Main extends React.Component {
  render() {

    // Map over the data and return the pleted ponent
    // On each iteration pass in the object data as `params`.
    // You can deconstruct this in the `InputText` ponent
    return data.map((input, i) => {
      return <InputText key={i} params={input} />
    });
  }
}

Now you can pick up those params in the ponent by deconstructing this.props.params and using those variables to fill out the ponent.

class InputText extends React.Component {

  constructor(props) {
    super(props);
    this.changeValue = this.changeValue.bind(this);
  }

  changeValue() {
    console.log('Placeholder to prevent bug');
  }

  render() {

   // Use destructuring to grab the individual properties from params
   const { type, name, classname, placeholder } = this.props.params;

    // Use those properties in the returned ponent elements
    return (
      <div className={classname}>
        <label htmlFor={name}>Test</label>
        <input
          onChange={this.changeValue}
          name={name}
          type={type}
          placeholder={placeholder}
        />
      </div>
    );
  }
}

DEMO

InputText.jsx

Upon interaction each InputText will raise onChange saying which input field was edited and what is its current value.

import * as React from 'react';

export class InputText extends React.Component {
  onChange = (e) => {
    const {onChange, name} = this.props;
    const {value} = e.target;
    if (onChange) {
      onChange(name, value);
    }
  }

  render() {
    const {name, title, type, placeholder, className, value} = this.props;
    return (
      <div className={className}>
        <label htmlFor={name}>{title}</label>
        <input
          placeholder={placeholder}
          name={name}
          type={type}
          value={value}
          onChange={this.onChange}
        />
      </div>
    );
  }
}

Form.jsx

Here we maintain the state of all inputs. The weird reduce is done to initialise the shape of the state with the input names being the object properties.

// initial state
{
  "FirstName": "",
  "Surname": ""
}

Upon edit this.setState({[name]: value}) the associated property gets updated.

import * as React from 'react';
import { InputText } from './InputText';

const inputs = [{
  "type": "text",
  "title": "some title",
  "name": "FirstName",
  "class": "text",
  "placeholder": "Enter first name"
}, {
  "type": "text",
  "title": "some other title",
  "name": "Surname",
  "class": "text",
  "placeholder": "Enter surname"
}];

export class Form extends React.Component {
  constructor(props) {
    super(props);
    this.state = inputs.reduce((acc, input) => {
      return {...acc, [input.name]: ''};
    }, {})
  }

  onChange = (name, value) => {
    this.setState({[name]: value});
  }

  render() {
    const list = inputs.map(input => {
      return (
        <InputText
          value={this.state[input.name]}
          key={input.name}
          type={input.type}
          name={input.name}
          title={input.title}
          className={input.class}
          placeholder={input.placeholder}
          onChange={this.onChange}
      />
      );
    });

    return (
      <form>
        {list}
      </form>
    );
  }
}

Assuming the JSON you want to iterate through is provided in an array you could do something like this. It will create a label and input element for each JSON.

render() {
  return (
    <div className={className}>
      {
      this.props.yourArray.map(value=>(
        <label htmlFor={value.name}>{value.title}</label>
        <input
          onChange={this.changeValue}
          name={value.name}
          type={value.type}
          value={value.value}
        />
      ))
      }
    </div>
  );
}

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1745548993a4632475.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信