Mike Tallerico
Mike Tallerico

Reputation: 125

Saving state of inputs added by user in React

I working on a small personal project using React on Rails. I am very new to both of these things.

I have a react component that is a form. I also have another component that has some inputs that the user can add as many as needed. Using the Add Properties button. I am trying to save the state of each input that is added. I could have the component itself save the state but how then would I send it with my fetch post request that happens onClick?

I have looked at react's context API but cant figure out if this would help me. Also I have never used redux so it is possible I should look into that as well.

https://reactjs.org/docs/context.html https://redux.js.org/basics/usagewithreact

I understand that I don't want to reach into state. So I was trying to figure out how to create an array of objects that will hold the input values of each input pair. But I cannot seem to wrap my mind around how to implement.

  class ProductsCreate extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      name: '',
      upc: '',
      availableOn: '',
      inputs: []
    };
    this.handleChange = this.handleChange.bind(this);
  }

  handleChange(e) {
    if (e.target.name === 'name') {
      this.setState({ name: e.target.value });
    }
    if (e.target.name === 'upc') {
      this.setState({ upc: e.target.value });
    }
    if (e.target.name === 'date') {
      this.setState({ availableOn: e.target.value });
    }
  }

  submitData = () => {
    fetch(`/send_data`, {
      method: 'POST',
      body: JSON.stringify({
        name: this.state.name,
        upc: this.state.upc,
        availableOn: this.state.availableOn
      }),
      headers: {
        'Content-Type': 'application/json'
      },
      credentials: 'same-origin'
    })
      .then(response => {
        return response.json;
      })
      .then(data => {
        console.log(data);
      });
  };

  clickHandler = e => {
    e.preventDefault();
    this.submitData();
  };

  appendInput = e => {
    e.preventDefault();
    const newInput = `input-${this.state.inputs.length}`;
    this.setState({ inputs: this.state.inputs.concat([newInput]) });
  };

  render() {
    return (
      <div className="form_container">
        <h1>Products</h1>
        <form>
          <label>Name</label>
          <input type="text" name="name" onChange={this.handleChange} />
          <label>UPC</label>
          <input type="text" name="upc" onChange={this.handleChange} />
          <label>Availiable On</label>
          <input
            type="text"
            name="date"
            placeholder="mm/dd/yyyy"
            onChange={this.handleChange}
          />
          <h1>Properties</h1>
          {this.state.inputs.map(input => (
            <Properties key={input} />
          ))}
          <button onClick={this.appendInput}>Add Properties</button>
          <button onClick={this.clickHandler}>Save</button>
        </form>
      </div>
    );
  }
}

export default ProductsCreate;

This is the component that will be added on click

import React from 'react';

class Properties extends React.Component {
  constructor(props) {
    super(props);
  }
  render() {
    return (
      <div className="property_container">
        <label>Property Name</label>
        <input type="text" name="propertyName" />
        <label>Property Value</label>
        <input type="text" name="propertyValue" />
      </div>
    );
  }
}

export default Properties;

Upvotes: 2

Views: 3071

Answers (1)

Shubham Gupta
Shubham Gupta

Reputation: 2646

Pass handle change as prop to Properties component and then use that prop in input onChange within your Properties component. Make the following edits. I also suggest if you don't want to continously update the state on every character typed use debounce.

ProductsCreate

      {this.state.inputs.map(input => (
        <Properties key={input} onChange={this.handleChange} name={input}/>
      ))}

Properties

      <input type="text" name={this.props.name} onChange={this.props.onChange}/>

Upvotes: 1

Related Questions