2

I have a class where I declare:

constructor() {
  super();
  this.state = {
    checked: false,
    house: [],
    selectedHouse: null
  };
  this.handleChange = this.handleChange.bind(this);
}

handleChange(checked) {
  this.setState({ checked });
}

render() {
  return (
    <React.Fragment>
        <TSwitch handleChange={this.handleChange.bind(this)} house={this.state.house} houseClicked={this.h}></TSwitch>
    </React.Fragment>

  );
}

I then want to set state.checked from a child component:

function TSwitch(props) {
  const handleChange = (house) => (evt) => {
    props.handleChange(house);
  };

  return (
    <div>
      {props.house.map((house) => {
        return (
          <label>
            <span>Switch with default style</span>
            <Switch onChange={handleChange} checked={this.state.checked} />
          </label>
        );
      })}
    </div>
  );
}

I am able to call handleChange but I want to be able to change the value of state.checked from the <TSwitch/> component.

1
  • onChange={handleChange} should be onChange={handleChange(house)} Commented Apr 12, 2020 at 12:00

3 Answers 3

1

This is what your parent component should be like:

constructor() {
  super();
  this.state = {
    checked: false,
    house: [],
    selectedHouse: null
  };
  this.handleChange = this.handleChange.bind(this);
}

handleChange(checked) {
  this.setState({ checked });
}

render() {
  return (
    <React.Fragment>
        <TSwitch handleChange={this.handleChange} isChecked={this.state.checked} house={this.state.house}></TSwitch>
    </React.Fragment>

  );
}

This is what your child component should look like:

function TSwitch(props) {

  return (
    <div>
      {props.house.map((house) => {
        return (
          <label>
            <span>Switch with default style</span>
            <Switch onChange={x => props.handleChange(x)} checked={props.isChecked} />
          </label>
        );
      })}
    </div>
  );
}

NOTE: You are using a Switch component, I'm not sure if the variable x will be a boolean or an object, but most probably it should be a boolean: true or false. If this doesn't work, log the value of x & see if its an object, and pass the boolean in props.handleChange. Although I still think this won't be needed. Good luck!

Sign up to request clarification or add additional context in comments.

Comments

0

1.

Let's start with your direct question

I want to be able to change the value of state.checked from the <TSwitch/> component

1.1 You've correctly passed your mutator function handleChange from the Parent class to TSwitch but your abstraction function handleChange inside that child, that you've duplicated, is unnecessary and should be removed completely.

1.2 Next, going back to the class' handleChange function, you need to modify the handleChange function definition in the parent component, by fixing the argument you passed it -- which will be the event object, passed implicitly since you registered it as a callback to onChange={handleChange} inside Tswitch. At invocation time, it will be called, and the evt argument that's given to onChange from React, will be passed into handleChange. But, you don't need it. It carries no information of necessity to you. So I would ignore it entirely.

// @ parent component

handleChange(evt) {
  // NOTE: i'm going to ignore the evt, since I don't need it.

  // NOTE: i'm going to use optional callback given by setState, to access prevState, and toggle the checked state boolean value.
  this.setState((prevState) => ({ checked: !prevState.checked }));
}


2.

Now let's clean up your code and talk about some best practices

2.1 You dont' need to be using React.Fragment here. Why? because Fragments were introduced in React 16 to provide a declarative API for handling lists of components. Otherwise, they're unecessary abstractions. Meaning: if you're not directly dealing with sibling components, then you don't need to reach for React.Fragment just go with a <div/> instead; would be more idiomatic.

2.2. If <TSwitch></TSwitch> isn't going to have a direct descendent, then you should change your usage syntax to <TSwitch/>.

2.3 If 2.2 didnt' get picked up by a linter, then I highly advised you install one.

2.4 You can continue using explicit bindings of your class handlers in your constructor if you'd like. It's a good first step in learning React, however, there's optimal ways to remove this boilerplate via Babel's transform properties plugins.

Comments

0

This will work:

handleChange(checked) {
  this.setState({ checked:!checked });
}

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.