0
votes

I have a simple React component which has one email input field and a checkbox like this:

interface MyProps {
  onSubmit?: (form: any) => void;
}
class Preferences extends React.Component<MyProps> {
  state = {
    primaryEmailCheckbox: false,
    primaryEmail: "",
  };

  onPrimaryEmailChange = e => {
    this.setState({ primaryEmail: e.target.value });
    let checkbox = document.getElementById("primaryEmailCheckId") as HTMLInputElement;
      checkbox.disabled = false; //<<< checkbox is null. lets say this is line 18
    }
  }

  render() {
    return (
        <StaticContent />
          <h3>Email Address</h3>
          <div className="ui mini icon input">
            <input type="email" value={this.state.primaryEmail} placeholder="Enter email..." onChange={this.onPrimaryEmailChange} />
          </div>
          <div className="ui checkbox">
            <input type="checkbox" disabled={true} id="primaryEmailCheckId" onChange={e => this.setState({ primaryEmailCheckbox: e.target.checked })} /><label> Continue to receive further email communications from Us </label>
          </div>
    );
  }
}
export default Preferences;

When anyone enters any thing on the email field, the checkbox becomes visible for user to check it or keep it unchecked. When I run the application, it works as expected. But when I test it, it says checkbox is null (at line 18), so you cannot set disabled on that. This is a test to test Preferences Component:

import * as React from "react";
import { shallow } from "enzyme";
import Preferences from "../../components/Preferences";

  test("Preferences shows email and checkbox", () => {
    const wrapper = shallow(<Preferences onSubmit={() => { }} />);
    wrapper.find("input").at(0).simulate("change", {
      target: {
        value: "a@b.c",
      }
    });
    expect(wrapper.find("input").state().value).toEqual("a@b.c");
  });

This throws Null exception at line 18. The thing is, the value a@b.c is passed correctly and I verified it by placing log statements. But, when I try to change the value of input type email, it calls a onChange method which tries to access (and change) the value of another input field.

I don't know how to change the value of 2nd input type which is a checkbox. How I can I make it work? Any help is appreciated.

1

1 Answers

1
votes

This is because the shallow(...) rendering method provides a limited set of interaction patterns and document.getElementById(...) is not one of them. You should be able to get what you want using the following:

const wrapper = mount(<Preferences />, { attachTo: document.body });

(Docs for the above code. You can swap out document.body for the relevant equivalent if you're using something like JSDOM or similar).

That said... using document.getElementById at all is a huge red-flag in React development. Because React lets you interact with a virtual DOM and handles the application of that to the real DOM, fiddling with the real one yourself is a great way to end up with all sorts of bugs. A much better option would be to use refs to access the checkbox in the "React way", or just make checkboxEnabled: boolean part of your state and update it inside your onPrimaryEmailChange() method.