Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Switch does not update when changing original status from undefined #9663

Closed
eleventy opened this issue Dec 29, 2017 · 7 comments

Comments

@eleventy
Copy link

commented Dec 29, 2017

  • I have searched the issues of this repository and believe that this is not a duplicate.

Expected Behavior

<Switch checked={this.props.isChecked} />
When this.props.isChecked is undefined( on initial render), the switch is off. When this.props.isChecked later updates to true, the switch should be on.

Current Behavior

When initial value is true or false, everything works as expected. When initial value = undefined, later updates do not show

Steps to Reproduce (for bugs)

https://codesandbox.io/s/04w6919x4v

In the sample, both switches should become true after timeout of 2000. checkedA with initial value of false works, checkedB remains unchecked.

Context

Checked prop should be Boolean or String, but sometimes initial values are undefined until server data arrives. a !!checkedB resolves the issue, but it can be very confusing.

Your Environment

Tech Version
Material-UI v1.0.0-beta.25
React 16.2.0
browser Firefox, Chrome
etc
@oliviertassinari

This comment has been minimized.

Copy link
Member

commented Dec 29, 2017

@eleventy The current behavior is the expected behavior. Have a look at #9525 for more detail.
However, we miss the following warning:

Warning: A component is changing an uncontrolled input of type checkbox to be controlled. Input elements should not switch from uncontrolled to controlled (or vice versa). Decide between using a controlled or uncontrolled input element for the lifetime of the component. More info: https://fb.me/react-controlled-components
in input (created by Switches)
in div (created by Switches)
in Switches (created by withStyles(Switches))
in withStyles(Switches)

I was able to get it by applying this simple change to your codesandbox demo:

        <Switch
          checked={this.state.checkedA}
          onChange={this.handleChange}
          aria-label="checkedA"
        />
-       <Switch
+       <input type="checkbox"
          checked={this.state.checkedB}
          onChange={this.handleChange}
          aria-label="checkedA"
        />

Fixing the missing warning should be as simple as changing this line:

checked={this.isControlled ? checkedProp : undefined}

-checked={this.isControlled ? checkedProp : undefined}
+checked={checkedProp}
@pietrofxq

This comment has been minimized.

Copy link

commented Jun 15, 2018

I just got bite by this issue. Spent half an hour trying to debug why my Switch that is receiving true is not enabling it on the UI. :(

@oliviertassinari

This comment has been minimized.

Copy link
Member

commented Jun 15, 2018

@pietrofxq Did you figure out the solution? Anything we could improve?

@abhisheksoni27

This comment has been minimized.

Copy link

commented Oct 15, 2018

I still have this issue. How do I solve it?

@pietrofxq

This comment has been minimized.

Copy link

commented Oct 15, 2018

@oliviertassinari @abhisheksoni27 This is indeed the correct behavior because it mimics the way controlled and uncontrolled components work in react. As long as there's the warning I don't see any problems with it. To fix it, just make sure that instead of undefined, the component receives false instead (you can use ES6 default values)

@eleventy

This comment has been minimized.

Copy link
Author

commented Oct 15, 2018

@abhisheksoni27 until it is permanently fixed, make sure the component never receives an undefined value by using something like !!myValue which turns an undefined to false

@abhisheksoni27

This comment has been minimized.

Copy link

commented Oct 15, 2018

Thanks @pietrofxq and @eleventy! I have tried doing that but I get the same result. Here's what I am doing:

  1. Render a TableHead. Inside TableBody, give it a this.state.userInfo children. This is initially null.

  2. Inside componentDidMount, make a fetch request to the server.

  3. When that Promise resolves, map the results array to that userInfo key in state returning a TableRow with the required values set inside TableCell. Here, every row contains a boolean which is what the Switch should use.

makeRequest("employees/getAll", "GET").then(resJson => {
      if (!resJson.err) {
        const accessGranted = {};
        resJson.data.forEach(row => {
          accessGranted[row._id] = row.accessGranted;
        });
        this.setState({ 
          ...accessGranted,
          usersData: resJson.data.map(row => {
            return (
              <TableRow className={classes.tableRow} key={row._id}>
// Othercode
// Switch Component

<Switch
                    checked={this.state[row._id]}
                    onChange={event => {
                      this.handleToggle(row._id);
                    }}
                    color="primary"
                  />
 );
          })
        }
      }
});

Since, the state will be set, shouldn't the toggle refresh itself again? If I set everything to false, it still doens't work the way I suppose it should. What do you think?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
4 participants
You can’t perform that action at this time.