0

I have built this site https://supsurvey.herokuapp.com/surveycreate/ now I am trying to move the fronted to React so I can learn React in the process.

with vanila js it was much easier to create elements dynamically. I just did createElement and after that when I clicked "submit" button I loop throw all the elements of Options and take each target.value input. so I loop only 1 time in the end when I click Submit and that's it I have now a list of all the inputs.

in react every change in each input field calls the "OnChange" method and bubbling the e.targe.value to the parent and in the parent I have to copy the current array of the options and rewrite it every change in every field.

is there other way? because it seems crazy to work like that.

Options.jsx

```import React, { Component } from "react";

class Option extends Component {
  constructor(props) {
    super(props);
    this.state = { inputValue: "", index: props.index };
  }

  myChangeHandler = event => {
    this.setState({ inputValue: event.target.value });
    this.props.onChange(this.state.index, event.target.value);
  };

  render() {
    return (
      <input
        className="survey-answer-group"
        type="text"
        placeholder="Add Option..."
        onChange={this.myChangeHandler}
      />
    );
  }
}

export default Option;

______________________________________________________________________________
Options.jsx````

```import React, { Component } from "react";
import Option from "./option";

class Options extends Component {
  render() {
    console.log(this.props);
    return <div>{this.createOptions()}</div>;
  }

  createOptions = () => {
    let options = [];
    for (let index = 0; index < this.props.numOfOptions; index++) {
      options.push(
        <Option key={index} onChange={this.props.onChange} index={index} />
      );
    }
    return options;
  };
}

export default Options;```
______________________________________________________________________________

App.jsx

```import React from "react";

import OptionList from "./components/Options";
import AddButton from "./components/add-button";
import "./App.css";

class App extends React.Component {
  state = {
    numOfOptions: 2,
    options: [{ id: 0, value: "" }, { id: 1, value: "" }]
  };

  handleChange = (index, value) => {
    const options = [...this.state.options];
    console.log("from App", value);

    options[index].value = value;
    this.setState({
      options: options
    });

    console.log(this.state);
  };

  addOption = () => {
    const options = [...this.state.options];
    options.push({ id: this.state.numOfOptions + 1, value: "" });

    this.setState({
      numOfOptions: this.state.numOfOptions + 1,
      options: options
    });
  };

  submitButton = () => {};

  render() {
    return (
      <div className="poll-create-grid">
        <div id="poll-create-options">
          <OptionList
            onChange={this.handleChange}
            numOfOptions={this.state.numOfOptions}
          />
        </div>
        <button
          className="surveyCreate-main-btn-group"
          onClick={this.addOption}
        >
          Add
        </button>
        <button
          className="surveyCreate-main-btn-group"
          onClick={this.submitButton}
        >
          Submit
        </button>
      </div>
    );
  }
}

export default App;
```
2
  • I found this online codesandbox.io/s/o54n9zwnly what is a good practice?
    – Eddie Knaz
    Commented Nov 11, 2019 at 11:50
  • Yea that's same thing you are trying to do but with React-hooks
    – delis
    Commented Nov 13, 2019 at 23:27

1 Answer 1

0

So firstly, The issue is with the way your OptionList component is defined.

Would be nice to pass in the options from the state into the component rather than the number of options

<OptionList
   onChange={this.handleChange}
   options={this.state.options}
/>

The you basically just render the options in the OptionsList component (I'm assuming it's same as the Options one here

class Options extends Component {
...
  render() {
    return 
      (<div>{Array.isArray(this.props.options) && 
        this.props.options.map((option) => <Option 
          key={option.id}
          index={option.id}
          onChange={this.props.onChange}
          value={option.value}
        />)}
      </div>);
  }
...
}

You would want to use the value in the Option component as well.

this.props.onChange(this.state.index, event.target.value); No need using the state here to be honest

this.props.onChange(this.props.index, event.target.value); is fine

1
  • what is the point passing options={this.state.options} there isn't value inside of them, the value is only when a user is typing inside input, so the value is only created in thr "Question" child
    – Eddie Knaz
    Commented Nov 11, 2019 at 9:21

Not the answer you're looking for? Browse other questions tagged or ask your own question.