1

Here's my code:

var questionsList = []

class PhotoDropZone extends Component {
  render() {
    return (
      <div id="dropZone">
        Drop a photo here.
      </div>
    );
  }
}

class Answers extends Component {

  constructor(props) {
    super(props);
    this.state = {
      answers: Array(4).fill(""),
      correctAnswers: [],
    };
    this.handleUpdate = this.handleUpdate.bind(this);
  }

  // let event = {
  //   index: 1,
  //   value: 'hello'
  // };
  handleUpdate (event) {
    //if ("1" == 1) // true
    //if ("1" === 1) //false 
    var answers = this.state.answers;
    answers[event.index] = event.value;
    this.setState(() => ({
      answers: answers
    }));

    console.log(event);
  }

  render () {
    return (
      <div id="answers">
                Answer Choices<br />
        {this.state.answers.map((value, index) => (
          <Answer value={value} key={index} onUpdate={this.handleUpdate} number={index}/>
        ))}
      </div>
    );
  }
}

class Answer extends Component {
  constructor(props) {
    super(props);
    this.state = {
      inputText: "",
      answer: props.value,
      correctAnswers: "",
    };
    this.handleChange = this.handleChange.bind(this);
  }

  handleChange(event) {
    const target = event.target;
    const value = target.type === "checkbox" ? target.checked : target.value;
    this.setState((previousState, props) => ({
      answer: value
    }));
    this.props.onUpdate({
      index: this.props.number,
      value
    });

    //
    // let sample = {
    //   kyle: "toast",
    //   cam: "pine"
    // };

    // sample.kyle
    // sample.cam

  }
  render () {
    return (
      <div>
        <input type="checkbox"/>
        <input type="text" value={this.state.answer} onChange={this.handleChange}/>
      </div>
    )
  }
}


var questionIdx = 0;

class Questions extends Component {
  constructor(props){
    super(props);
    this.state = {
      questions:[]
    }
    this.handleUpdate = this.handleUpdate.bind(this);
  }

  handleUpdate (event) {
    //if ("1" == 1) // true
    //if ("1" === 1) //false 
    var questions = this.state.questions
    questions[event.index] = event.value;
    this.setState(() => ({
      questions: questions
    }));

    console.log(event);
  }

  addQuestion = question => {
    questionIdx++;
    this.setState(prevState => ({
      questions: [...prevState.questions, question]
    }));
  };

  removeQuestion () {
    console.log("remove button");
  }

  render () {
    return (
      <div id="questions">
        <ol id="quesitonsList">
           {this.state.questions.map((value, index)=> (
            <li id={"questionLi" + uuid()}>
              {<Question onUpdate={this.handleUpdate} value={value} number={index}/>}
              {<RemoveQuestionButton onClick={this.removeQuestion}/>}
            </li>
          ))}
        </ol>
        <AddQuestionButton onClick={this.addQuestion} />
      </div>
    );
  }
}

class Question extends Component {
  constructor(props){
    super(props);
    this.state = {
      question: ""
    }
    this.handleChange = this.handleChange.bind(this);
  }

  handleChange(event) {
    const target = event.target;
    const value = target.type === "checkbox" ? target.checked : target.value;
    this.setState((previousState, props) => ({
      question: value
    }));
      this.props.onUpdate({
        index: questionIdx,
        value
      });
  }

  render () {
    return (
      <div id={"questionDiv" + questionIdx}>
        Question<br />
        <input type="text" value={this.state.question} onChange={this.handleChange} />
        <PhotoDropZone />
        <Answers />
      </div>
    );
  }
}

class IntroFields extends Component {
  constructor (props) {
    super(props);
    this.state = {
      title: "",
      author: ""
    }
    this.handleChange = this.handleChange.bind(this);
  }

  handleChange(event) {
    const target = event.target;
    const value = target.type === "checkbox" ? target.checked : target.value;
    const name = target.name;
    console.log([name]);
    this.setState((previousState, props) => ({
      [name]: value
    }));
  }

  render () {
    return (
      <div id="IntroFields">
        Title: <input type="text" value={this.state.title} onChange={this.handleChange} name="title"/>
        Author: <input type="text" value={this.state.author} onChange={this.handleChange} name="author"/>
      </div>
    );
  }
}

class AddQuestionButton extends Component {

  addQuestion = () => {
    this.props.onClick(
      <Question onUpdate={this.handleUpdate} value={this.value} number={this.index}/>
    );
  };

  render () {
    return (
      <div id="addQuestionButtonDiv">
        <button id="addQuestionButton" onClick={this.addQuestion}>Add Question</button>
      </div>
    );
  }
}

class RemoveQuestionButton extends Component {

  removeQuestion = () => {
    this.props.onClick(
      <Question onUpdate={this.handleUpdate} number={questionIdx}/>
    );
  }

  render () {
    return (
      <div id="removeQuestionButtonDiv">
        <button id="removeQuestionButton" onClick={this.removeQuestion}>Remove Question</button>
      </div>
    )
  }
}

class BuilderForm extends Component {
  render() {
    return (
      <div id="formDiv">
        <IntroFields />
        <Questions />
      </div>
    );
  }
}
export default BuilderForm;

So this is a form that has an Add Question button that adds a whole section of a form to the form. I am having an issue with my questions and question states. When I add the initial question and start typing in my Question input, another section is added (as if the Add Question button was pressed again) and I notice that two items are added to my questions array, one more object array and a string of what I typed in. Every time I click the Add Question button another object array thing is added to the questions array and it doesn't matter which "Question" input I type in, the string object (inside of the questions array) is updated. Ideally each section of the form would update its own state.

I am not sure why this is happening, I am new to React and JS so even a little explanation of what you think is going on would be very insightful.

If you need more explanation just let me know and I will try my best to explain. I've tried to get this on CodePen and other things but I am never successful at doing so. Thanks ahead of time.

UPDATE: I was able to get it on CodeSandbox

6
  • 3
    It's much more likely that you will get help if you isolate your problem in a Minimal, Complete, and Verifiable example, and create e.g. a CodeSandbox that illustrates it. Commented Jul 23, 2018 at 20:21
  • @Tholle I was able to get it on CodeSandbox, I updated my question with the link Commented Jul 23, 2018 at 20:39
  • 1
    The codesandbox seems to be pretty empty, as far as I can see. However, from reading the code, you seem to mutate the state, rather than updating it. In your handleUpdate you retrieve the state, and add a new entry. ideally, one would create a new state and then update the newly created array Commented Jul 23, 2018 at 20:44
  • Darn, the CodeSandbox thing must not be saving correctly, sorry about that. And thanks for the advice, I'll try that out Commented Jul 23, 2018 at 20:50
  • @Icepickle the CodeSandbox should be working now Commented Jul 23, 2018 at 20:55

1 Answer 1

2

questionIdx will be 1 larger than expected, so it will create a new question when used.

Use this.props.number instead in the handleUpdate method of the Question component.

handleChange(event) {
  const target = event.target;
  const value = target.type === "checkbox" ? target.checked : target.value;
  this.setState({
    question: value
  });
  this.props.onUpdate({
    index: this.props.number,
    value
  });
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.