0

I have a parent? class that hosts a random question and different types of user input that depend on the type of question.

  1. 3 clickable buttons that change color on click
  2. an input box
class Parent extends Component {
   state = {
   buttonColors: ["white", "white", "white"],
   questionType: 0,
   avg: 0,
   numbers: [],
   answer: "",
   number: 0,
   showAns: false,
   current: "",
   etc....
   }

   // This part basically handles clicking of 3 buttons
   clickedAnswer(userAnswer) {
     // 0 is (>)   //   1 is (=)        1 is (<)
     let colors = this.state.buttonColors;
     let guess = this.state.current;
     if (!guess.includes(1)) {
     //Hasn't Guessed Yet -Action- Select Clicked button
     //Change color of the Guessed button
     colors[userAnswer] = "#d0f0c0";
     guess[userAnswer] = 1;
     } else {
     //Clicked Previous Answer -Action- Unselect Clicked button
     colors = ["white", "white", "white"]; //Reset Colors
     colors[userAnswer] = "#d0f0c0";
     guess = [0, 0, 0]; // Reset Guess
     guess[userAnswer] = 1;
    }

    this.setState({
    current: guess,
    buttonColors: colors,
    });
  }
   
   render() {
      return (
         <RenderInput
                questionType={this.state.questionType}
                answer={this.state.answer}
                buttonColors={this.state.buttonColors}
                clickedAnswer={this.clickedAnswer}
                handleChange={this.handleChange}
                current={this.state.current}
                showAns={this.state.showAns}
                />
      )
   }

and then I have a const Render at the bottom of my file which dynamically renders the input type depending on the questionType.

const RenderInput = (props) => {
    switch (props.questionType){
        case 0: case 1: case 2: case 3:
            return (
                <Row style={{ paddingBottom: "50px", paddingTop: "50px" }}>
                  <Col style={{height: 100, textAlign: "right"}}>
                    <button
                        id="btn1"
                        onClick={() => props.clickedAnswer(0)}
                        style={{
                        width: "200px",
                        height: "80px",
                        backgroundColor:
                            props.showAns && props.answer[0] === 1
                            ? "red"
                            : props.buttonColors[0],
                        }}
                    >
                        <span
                        style={{ fontFamily: "courier", fontSize: "35px" }}
                        >
                            {"Higher"}
                        </span>
                    </button>
                  </Col>

                  <Col style={{ height: 100, textAlign: "center" }}>
                    <button
                    id="btn2"
                    onClick={() => props.clickedAnswer(1)}
                    style={{
                        width: "250px",
                        height: "80px",
                        backgroundColor:
                        props.showAns && props.answer[1] === 1
                            ? "red"
                            : props.buttonColors[1],
                    }}
                    >
                    <span
                        style={{ fontFamily: "courier", fontSize: "35px" }}
                    >
                        {"Unchanged"}
                    </span>
                    </button>
                  </Col>

                  <Col style={{height: 100, textAlign: "left"}}>
                    <button
                        id="btn3"
                        onClick={() => props.clickedAnswer(2)}
                        style={{
                          width: "200px",
                          height: "80px",
                          backgroundColor:
                            props.showAns && props.answer[2] === 1
                              ? "red"
                              : props.buttonColors[2],
                        }}
                    >
                        <span
                          style={{ fontFamily: "courier", fontSize: "35px" }}
                        >
                          {"Lower"}
                        </span>
                    </button>
                  </Col>
                </Row>
            )
        case 4: case 5:
            return (
                <p
                style={{
                  fontSize: 25,
                  textAlign: "center",
                  fontFamily: "courier",
                  fontWeight: "bold",
                  paddingTop: "10px",
                }}
                >
                    <input
                        type="text"
                        value={props.current}
                        onChange={props.handleChange}
                        id="input1"
                        autoComplete="off"
                        maxLength="8"
                        style={{
                        color: !props.showAns ? "black" : "red",
                        fontSize: 55,
                        fontFamily: "courier",
                        fontWeight: "bold",
                        width: "280px",
                        height: "85px",
                        textAlign: "center",
                        }}
                    />
                </p>
            )
    }
}

However when I try to click the button the change the color, I get an error saying cannot read property 'buttonColor' of undefined

How do I fix this? I basically need the child? or const component to return an action user clicked button 1/2/3 to the method clickedAnswer which changes the button color based on the button # and then send that updated color scheme back to the const and re-render the input section to reflect the color update.

Connell.O'Donnell
  • 3,603
  • 11
  • 27
  • 61
Jeffrey
  • 63
  • 9

1 Answers1

2

When you call clickedAnswer={this.clickedAnswer}, the this reference is null within the method. Replace it with clickedAnswer={this.clickedAnswer.bind(this)} to bind to the current object so that it will have access to the state.

You can read about the bind method here: Function.prototype.bind()

Connell.O'Donnell
  • 3,603
  • 11
  • 27
  • 61