1

Here's my current code:

/* ************************************* */
/* ********       IMPORTS       ******** */
/* ************************************* */
import React, { Component } from 'react';
import UUID from 'node-uuid';
import { Card, CardBlock, Button, InputGroup, Input } from 'reactstrap';
import ProviderInfos from '../ProviderInfos/ProviderInfos';

/* ************************************* */
/* ********      VARIABLES      ******** */
/* ************************************* */

/* ************************************* */
/* ********      COMPONENT      ******** */
/* ************************************* */
export default class PretzelStandComponent extends Component {

    constructor(props) {
        super(props);
        this.state = { 
            inputPretzel: [],
            inputCurry: [],
            inputWurst: []
            };
        this.incrementPretzel = this.incrementPretzel.bind(this);
        this.incrementCurry = this.incrementCurry.bind(this);
        this.incrementWurst = this.incrementWurst.bind(this);
        this.decrementPretzel = this.decrementPretzel.bind(this);
        this.decrementCurry = this.decrementCurry.bind(this);
        this.decrementWurst = this.decrementWurst.bind(this);
    }

    componentDidMount() {
        this.incrementPretzel();
        this.incrementCurry();
        this.incrementWurst();
    }

    incrementPretzel() {
        const uuid = require('uuid/v1');
        uuid();
        const inputPretzel = this.state.inputPretzel;
        this.setState({
            inputPretzel: inputPretzel.concat(<InputGroup>
                <Input placeholder="Pretzel" key={uuid} /><ProviderInfos /></InputGroup>),
        });
    }

    incrementCurry() {
        const uuid = require('uuid/v1');
        uuid();
        const inputCurry = this.state.inputCurry;
        this.setState({
            inputCurry: inputCurry.concat(<InputGroup>
                <Input placeholder="Curry" key={uuid} /><ProviderInfos /></InputGroup>),
        });
    }

    incrementWurst() {
        const uuid = require('uuid/v1');
        uuid();
        const inputWurst = this.state.inputWurst;
        this.setState({
            inputWurst: inputWurst.concat(<InputGroup>
                <Input placeholder="Wurst" key={uuid} /><ProviderInfos /></InputGroup>),
        });
    }

    decrementPretzel() {
        this.setState({
            inputPretzel: this.state.inputPretzel.splice(this.state.inputPretzel, this.state.inputPretzel.length - 1),
        });
    }

    decrementCurry() {
        this.setState({
            inputCurry: this.state.inputCurry.splice(this.state.inputCurry, this.state.inputCurry.length - 1),
        });
    }

    decrementWurst() {
        this.setState({
            inputWurst: this.state.inputWurst.splice(this.state.inputWurst, this.state.inputWurst.length - 1),
        });
    }

    render() {
        return (
            <Card>
                <CardBlock className="main-table">
                    <fieldset>
                        <legend>Pretzels</legend>
                        {this.state.inputPretzel}
                        <button onClick={this.incrementPretzel}>Add a Pretzel</button>
                        <button onClick={this.decrementPretzel}>Remove a Pretzel</button>
                    </fieldset>
                    <fieldset>
                        <legend>Curry</legend>
                        {this.state.inputCurry}
                        <button onClick={this.incrementCurry}>Add Curry</button>
                        <button onClick={this.decrementCurry}>Remove Curry</button>
                    </fieldset>
                    <fieldset>
                        <legend>Wurst</legend>
                        {this.state.inputPretzel}
                        <button onClick={this.incrementPretzel}>Add Wurst</button>
                        <button onClick={this.decrementPretzel}>Remove Wurst</button>
                    </fieldset>
                    <Button color="secondary">Options</Button>{' '}
                    <Button id="btn">Exécuter</Button>
                </CardBlock>
            </Card>
        );
    }
}

As you can see I have three different elements and collections of these elements:

  • Pretzels
  • Currys
  • and Wursts

I can add them and remove the last one. but I'd like to remove each one.

In the Html code that I'm placing in the setState and adding to each collection I want to append a delete button or somehow have a delete button next to each line which deletes the right line.

Jason Aller
  • 3,541
  • 28
  • 38
  • 38
tatsu
  • 2,316
  • 7
  • 43
  • 87

1 Answers1

2

Update

I added some parts to keep track of input state and add a value to each item:

  • pretzelValue
  • curryValue
  • wurstValue

These are the value of the inputs, which are then passed into the increment functions. Also removed input from the FoodType component, if you want to be able to edit them it's a bit trickier.


Original

You can clean it up a bit by just using arrays of objects for the sets of food. Then using another component for the FoodType should make it much cleaner and give good performance for onClick. Each item has it's own uuid, so you can .filter on that to remove the item from the state. The state and functions to add/remove could be more generic, but this is a decent start. Something like this:

const uuid = require('uuid/v1');

export default class PretzelStandComponent extends Component {
  state = {
    pretzels: [],
    curries: [],
    wursts: [],
    pretzelValue: '',
    curryValue: '',
    wurstValue: ''
  }

  componentDidMount() {
  }

  incrementPretzel = () => {
    this.setState({
      pretzels: this.state.pretzels.concat([{id: uuid(), value: this.state.pretzelValue}]),
      pretzelValue: ''
    });
  }

  incrementCurry = () => {
    this.setState({
      curries: this.state.curries.concat([{id: uuid(), value: this.state.curryValue}]),
      curryValue: ''
    });
  }

  incrementWurst = () => {
    this.setState({
      wursts: this.state.wursts.concat([{id: uuid(), value: this.state.wurstValue}]),
      wurstValue: ''
    });
  }

  decrementPretzel = (id) => {
    this.setState({
      pretzels: this.state.pretzels.filter((pretzel) => pretzel.id !== id)
    });
  }

  decrementCurry = (id) => {
    this.setState({
      curries: this.state.curries.filter((curry) => curry.id !== id)
    });
  }

  decrementWurst = (id) => {
    this.setState({
      wursts: this.state.wursts.filter((wurst) => wurst.id !== id)
    });
  }

  onPretzelChange = (event) => {
    this.setState({
      pretzelValue: event.target.value
    });
  }

  onCurryChange = (event) => {
    this.setState({
      curryValue: event.target.value
    });
  }

  onWurstChange = (event) => {
    this.setState({
      wurstValue: event.target.value
    });
  }

  render() {
    const {pretzels, curries, wursts} = this.state;
    return (
      <Card>
        <CardBlock className="main-table">
          <fieldset>
              <legend>Pretzels</legend>
              {pretzels.map((pretzel) => (
                <FoodType id={pretzel.id} placeholder="Pretzel" onRemove={this.decrementPretzel} value={pretzel.value} />
              ))}
              <input onChange={this.onPretzelChange} value={this.state.pretzelValue} />
              <button onClick={this.incrementPretzel}>Add a Pretzel</button>
          </fieldset>
          <fieldset>
              <legend>Curry</legend>
              {curries.map((curry) => (
                <FoodType id={curry.id} placeholder="Curry" onRemove={this.decrementCurry} value={curry.value} />
              ))}
              <input onChange={this.onCurryChange} value={this.state.curryValue} />
              <button onClick={this.incrementCurry}>Add Curry</button>
          </fieldset>
          <fieldset>
              <legend>Wurst</legend>
              {wursts.map((wurst) => (
                <FoodType id={wurst.id} placeholder="Wurst" onRemove={this.decrementWurst} value={wurst.value} />
              ))}
              <input onChange={this.onWurstChange} value={this.state.wurstValue} />
              <button onClick={this.incrementWurst}>Add Wurst</button>
          </fieldset>
          <Button color="secondary">Options</Button>{' '}
          <Button id="btn">Exécuter</Button>
        </CardBlock>
      </Card>
    );
  }
}

FoodType component

class FoodType extends Component {
  onRemove = () => {
    this.props.onRemove(this.props.id);
  }

  render() {
    const {placeholder, id, value} = this.props;
    return (
      <InputGroup>
        <div key={id}>{value}</div>
        <ProviderInfos />
        <button onClick={this.onRemove}>X</button>
      </InputGroup>
    );
  }
}

Also cleaned up the binds with the property initializer syntax.

Austin Greco
  • 32,997
  • 6
  • 55
  • 59
  • this is actually really good and quite what I'm looking for! I went ahead and implemented it and took the liberty of making the seperate food type comonent a full-blown import. but bizarely when I click an "x" it removes all the elements for that food type – tatsu Aug 10 '17 at 09:53
  • I think what's happening is the ``s are being re-rendered which wipes out the value, since it's not being saved anywhere in the state. This needs a bit of rework to add the value as part of the object along with the id and then pass it into the `incrementX` functions. I can update the example if you need more info. – Austin Greco Aug 10 '17 at 18:49
  • yeah defnitely! please :) are you trying to say there should be a counter passed down to the foodtype component as well as the increment and decrement functions? I don't get it. – tatsu Aug 11 '17 at 07:39
  • I updated the code above, check out how it keeps the input value in the state, and then adds it to the array items as `value`. – Austin Greco Aug 11 '17 at 07:55
  • Ok I think I get it now In your setup you are supposed to fill the top input then click on add to add another input and it gets moved down. The problem is not only do I want to allow the user to first add inputs then fill them in, I want the new inputs to be on the bottom of the list not on top. – tatsu Aug 11 '17 at 08:38