Closed oquirozm closed 5 years ago
The components state is based on the checked
prop you pass to it. You need to change the value of ´isRunning´ in the onChange handler. It should look something like this if isRunning is part of your state:
<Switch
onChange={checked => {
this.setState({isRunning: checked})
}}
checked={isRunning}
/>
I am running into a similar issue, even though I am changing the state in the onChange handler.
handleChange(checked) {
this.setState({ checked });
}
render() {
const { id, children } = this.props;
const { checked } = this.state;
return (
<div>
<label htmlFor={id}>
{children}
<Switch
className="react-switch"
uncheckedIcon={false}
checkedIcon={false}
onColor={colorPrimary}
onChange={this.handleChange}
checked={checked}
id={id}
/>
</label>
</div>
);
}
In the GIF below, you can see:
I am also using React 16.8.1 and react-switch 4.0.1.
PS: I've just tried using touch and it does work when touching on the handle.
Ok, I may have found why this happens.
My switch is within a Chrome Extension, which runs within an iframe.
When clicking on the handle, the mouse down event is fired correctly (and handled by the react component), however, it's adding an event listener in window
, which doesn't match the window
in which the mouse up will be fired. The mouse-up event is then "missed" by the component and it doesn't toggle.
Any idea on how to mitigate this?
@markusenglund got it, solved it. I think we can close the issue.
@superzadeh I have no idea how you could work around this, sorry.
@superzadeh I tried to put the react-switch demo inside a chrome extension as a popup.
"browser_action": {
"default_popup": "index.html"
}
It works fine for me (Chrome 71, MacOS). What do you do to make it break?
The setup is more complex in our case, as our extension is a sidebar running on other websites; to isolate CSS and other things, we run the sidebar within an iframe using react-frame-component.
I've written a repro example here: https://codesandbox.io/s/l5opn8q3p9
Thanks for the repro. It seems difficult to support iframes since they have their own window object.
If you really want to use react-switch I guess you could patch it in your project with patch-package to add a window prop to the component, and use it instead of normal window like:
$onMouseUp(event) {
const { window } = this.props;
this.$onDragStop(event);
window.removeEventListener("mousemove", this.$onMouseMove);
window.removeEventListener("mouseup", this.$onMouseUp);
}
But even so, the dragging will only work inside the iframe.
Yeah, I ended up rolling my own component; slightly more limited in functionality but at least it works in the iframe.
A nice update for this project would be to allow passing a custom window/callback to get the window object;
import ReactDOM from "react-dom";
import React, { Component } from "react";
import Switch from "react-switch";
import Frame, { FrameContextConsumer } from "react-frame-component";
class SwitchExample extends Component {
constructor() {
super();
this.state = { checked: false };
this.handleChange = this.handleChange.bind(this);
}
handleChange(checked) {
this.setState({ checked });
}
render() {
return (
<Frame>
<FrameContextConsumer>
{// Callback is invoked with iframe's window and document instances
(frameContext) => {
// Render Children
return (
<div>
<p>Switch with default style</p>
<Switch
window={frameContext.window}
onChange={this.handleChange}
checked={this.state.checked}
/>
</div>
);
}}
</FrameContextConsumer>
</Frame>
);
}
}
ReactDOM.render(<SwitchExample />, document.getElementById("root"));
I'm attaching a gif showing the behavior. When I click on the switch it doesn't do anything at all. It can only be toggled by dragging it and even then the animation makes a jump. https://gfycat.com/VagueNeglectedBonobo
I'm using React 16.8.1 and react-switch 4.0.1 in a create-react-app project where I manually updated React. Here's how I'm using the switch:
What could be causing the behavior?