1

just wondering how I can fix this? I heard about using consumers but I don't think this will resolve the issue, since I need to call setSaveEnabled in the handleChange() function, which cannot be defined inside of a consumer if I were to make one. What other paths is there which I can take?

I call handleChange() inside of the onchange arguement in the switch component.

import SaveContext from "../../context/SaveContext";
class EnableSwitch extends Component {
  constructor() {
    super();
    this.state = { checked: false };
    this.handleChange = this.handleChange.bind(this);
  }

  handleChange(checked) {
    this.setState({ checked });
    const { setSaveEnabled } = useContext(SaveContext);
    setSaveEnabled(false);
  }

  render() {
    return (
      <div>
        <Switch
          checked={this.state.checked}
          onChange={() => {
            this.handleChange();
          }}
        />
      </div>
    );
  }
}
React Hook "useContext" cannot be called in a class component. React Hooks must be called in a React function component or a custom React Hook function
Drew Reese
  • 165,259
  • 14
  • 153
  • 181
jaal kamza
  • 213
  • 4
  • 12
  • Hooks FAQ - You can’t use Hooks inside a class component, but you can definitely mix classes and function components with Hooks in a single tree – nart Mar 21 '22 at 01:29
  • By putting the function component outside of the class? – jaal kamza Mar 21 '22 at 01:53
  • nahh they say you can use both functional component and class component within an app. In you case, just convert class to function component – nart Mar 21 '22 at 01:58

1 Answers1

2

React hooks are only valid in React function components.

You can either convert this class component to a function component:

import SaveContext from "../../context/SaveContext";

const EnableSwitch = () => {
  const { setSaveEnabled } = useContext(SaveContext);  
  const [checked, setChecked] = React.useState(false);

  const handleChange = checked => {
    setChecked(checked);
    setSaveEnabled(false);
  }

  return (
    <div>
      <Switch
        checked={checked}
        onChange={this.handleChange}
      />
    </div>
  );
}

Or if conversion is unacceptable or cumbersome (too many props, too many class components, etc...) then you can create a Higher Order Component to access the React context and inject the setSaveEnabled function as a prop:

const withSaveContext = Component => props => {
  const { setSaveEnabled } = useContext(SaveContext);
  return <Component {...props} setSaveEnabled={setSaveEnabled} />;
}

...

import SaveContext from "../../context/SaveContext";

class EnableSwitch extends Component {
  constructor() {
    super();
    this.state = { checked: false };
    this.handleChange = this.handleChange.bind(this);
  }

  handleChange(checked) {
    this.setState({ checked });
    this.props.setSaveEnabled(false);
  }

  render() {
    return (
      <div>
        <Switch
          checked={this.state.checked}
          onChange={this.handleChange}
        />
      </div>
    );
  }
}
Drew Reese
  • 165,259
  • 14
  • 153
  • 181