react-switch icon indicating copy to clipboard operation
react-switch copied to clipboard

Switch is only draggable, not toggled by click

Open KidA001 opened this issue 4 years ago • 13 comments

I'm on React 16.12.0 and react-switch 5.0.1

When I render react-switch it is only draggable, but does not change/toggle when I click it. I found this issue however that seemed related to an iFrame which I'm not using.

I put a console.log(checked) in the handleChange function and it always outputs false regardless of what the state of the switch is.

Below is the component I'm loading the switch in. My only guess is it might have something to do with the async methods or with me setting the state in the View() function, but it's not clear to me what I'm doing wrong.

import React, { Component } from "react"
import axios from 'axios';
import Switch from "react-switch";

import HidingContainer from "../HidingContainer"
import NumericValue from "../NumericValue/index"


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

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

  async componentDidMount() {
    await this.View();
  }

  CustomSwitch = () => {
    return (
      <Switch
        onChange={this.handleChange}
        checked={this.state.checked}
        onColor="#86d3ff"
        onHandleColor="#2693e6"
        handleDiameter={30}
        uncheckedIcon={false}
        checkedIcon={false}
        boxShadow="0px 1px 5px rgba(0, 0, 0, 0.6)"
        activeBoxShadow="0px 0px 1px 10px rgba(0, 0, 0, 0.2)"
        height={20}
        width={48}
        className="react-switch"
        id="material-switch"
      />
    )
  }

  async getHotTubStatus() {
    const response = await axios({
      url: "http://localhost:3000/hot-tub-status",
      method: 'get'
    });

    return response.data
  }

  async View() {
    const hotTubStatus = await this.getHotTubStatus()

    this.setState({
      checked: hotTubStatus.on, // sets initial state
      View: (
        <NumericValue value={hotTubStatus.temperature} unit="°F" />
        <this.CustomSwitch />
      )
    })
  }

  render() {
    return (
      <HidingContainer metricsRef={React.createRef()}>
        {this.state.View}
      </HidingContainer>
    )
  }
}

export default HotTub

Any insight/help appreciated

KidA001 avatar Jun 09 '20 19:06 KidA001

UP! I have the same problem.

MrWillian avatar Jul 18 '20 19:07 MrWillian

can you tell me how to make the circle part offcolor when i'm not clicking or focusing it !

adarshaacharya avatar Jul 19 '20 10:07 adarshaacharya

Bump. I'm having the same issue

amosyu2000 avatar Aug 04 '20 01:08 amosyu2000

@KidA001 I might not be correct with this, but could it be because every time you try to change the checked state, you call a setState which will cause the component to be re-rendered, which will then cause componentDidMount to trigger every time, so you're fetching the same checked state again from the server, so basically the switch always sets back to the same value.

Try to find a way to call View() only once when the component is loaded first either by getting the contents of View() from the parent component, setting a falsy local variable to true after the first mount and check for it the 2nd time, or if you are using hooks, provide an empty array as the second argument of useEffect().

benomatis avatar Oct 14 '20 10:10 benomatis

Hi, sorry for the late response.

@KidA001 Rendering the CustomSwitch component in the state of the parent, and at the same time trying to read state from the parent inside the CustomSwitch is definitely going to lead to unexpected behavior. Here's a sandbox which should work better: https://codesandbox.io/s/dark-snowflake-mms03?file=/src/index.js

To everyone else in the thread: Could you fork this Code sandbox and create a minimal reproduction of the issue you're facing?

EDIT: Here's a version that still works: https://codesandbox.io/s/jolly-ishizaka-k574z?file=/src/index.js

markusenglund avatar Dec 12 '20 19:12 markusenglund

Hey still facing the same issue <SwitchCheckBox onChange={handleChange} checked={checked} uncheckedIcon={false} checkedIcon={false} onColor="#86d3ff" onHandleColor="#2693e6" handleDiameter={30} boxShadow="0px 1px 5px rgba(0, 0, 0, 0.6)" activeBoxShadow="0px 0px 1px 10px rgba(0, 0, 0, 0.2)" height={20} width={48} className="react-switch" id="material-switch" />

const handleCheckBox = (checked) => { setFormData({ ...formData, isMonitoringStock: checked }) } Can please anyone tell me what,s the issue

iamAbdulAhad3481 avatar Jan 25 '21 11:01 iamAbdulAhad3481

One way around this problem is to pass an empty callback function to the Switch and then wrap that Switch with a div element. Then pass onTap/onClick callback function to this div element. It will also allow you to drag and toggle if you don't drag the cursor out of the Switch UI model. (I did not find any way around this, frankly it doesn't bother me so I did not try to find any)

BSiddharth avatar Oct 06 '21 12:10 BSiddharth

@iamAbdulAhad3481

Hey still facing the same issue <SwitchCheckBox onChange={handleChange} checked={checked} uncheckedIcon={false} checkedIcon={false} onColor="#86d3ff" onHandleColor="#2693e6" handleDiameter={30} boxShadow="0px 1px 5px rgba(0, 0, 0, 0.6)" activeBoxShadow="0px 0px 1px 10px rgba(0, 0, 0, 0.2)" height={20} width={48} className="react-switch" id="material-switch" />

const handleCheckBox = (checked) => { setFormData({ ...formData, isMonitoringStock: checked }) } Can please anyone tell me what,s the issue

This largely depends on how the checked state looks like in your app, what triggers its change, and lifecycle hooks you have that influence it... etc; the code you pasted unfortunately doesn't have this info.

As a general rule of thumb, this appears to be an issue with the incorrect handling of the checked state, ie. it's either not changing on click, or it's immediately changing again or changing indefinitely in the background back and forth.

What I do in cases like this to troubleshoot is I create a small line that's printing out the value of a state, something around the lines of <div>{ checked ? 'checked' : 'not' }</div>.

benomatis avatar Oct 06 '21 12:10 benomatis

@BSiddharth Could you provide a reproduction of the issue in code sandbox and explain the issue as well as what platform & browser are affected?

markusenglund avatar Oct 07 '21 19:10 markusenglund

@markusenglund Interestingly the simple code I wrote in the sandbox works. I will check my full code and will update it here later when I get time.

Edit - Well it works now for some reason. I just uncommented the old code and commented the new one. And its working okay. Maybe because I updated to the latest Firefox 93.0 since last I ran that code??

BSiddharth avatar Oct 08 '21 06:10 BSiddharth

I have the same problem on macOS now, with the recent Chrome version 96.0. It worked before. But now, I can enable a switch, but not disable it. And even worse: if you try to switch multiple switches on a page, all of the sudden all switches move. This does not happen on iOS or Firefox. On Android, it kinda works, but sometimes the animations are missing.

derwaldgeist avatar Nov 20 '21 09:11 derwaldgeist

Can anyone confirm derwaldgeist problem? As I wrote in his issue I don't have access to a MacOS device. I briefly tested the demo page on chrome 96 on macos via browserstack and couldn't reproduce the issue on the demo page.

markusenglund avatar Nov 25 '21 22:11 markusenglund

Hi @markusenglund: Closing this. It seems as if this was a temporary hick-up of Chrome which vanished after I restarted my Mac. Sorry for the confusion.

derwaldgeist avatar Nov 26 '21 12:11 derwaldgeist