简体   繁体   中英

Checkbox state not toggle. Material UI React

I use Material UI checkbox component, and try toggle state onCheck, in console state changes but in UI not, the check mark does not toggle. what did I mess.

class CheckboxInteractivity extends React.Component {

    state = {
        switched: false,
    }

    componentWillMount() {
        const {checked} = this.props
        if (checked) {
            this.setState({
                switched: true,
            })
        }
    }

    handleChange = (event, switched) => {
        this.setState({switched: !this.state.switched})
    }

    render () {
        const {switched} = this.state

        return <Checkbox
            label="Label"
            checked={switched}
            onCheck={this.handleChange}
            {...this.props}
                />
    }
}

CheckboxInteractivity.propTypes = {
    checked: PropTypes.bool,
}

export default CheckboxInteractivity

components

<CheckboxInteractivity /> 
//working correctly
<CheckboxInteractivity checked/>
//not working 

Reason why it is not working with second case is:

return <Checkbox
            label="Label"
            checked={switched}
            onCheck={this.handleChange}
            {...this.props}
       />

Will become:

return <Checkbox
            label="Label"
            checked={switched}
            onCheck={this.handleChange}

            checked={true}                     //here

       />

You are using two checked property and second will make the checkbox checked true always irrespective of the state variable that's why. Remove {...this.props} it will work as expected.

Why it is working in first case is, you are not passing the checked so checkbox will find only one checked key and it will render the component on the basis of that.

Here {...this.props} is not required because you are already storing the value in state .

Suggestion:

Instead of setting the props value in state in componentWillMount lifecycle method set that in constructor only, like this:

constructor(props){
    super(props);
    this.state = {
        switched: props.checked || false,
    }
}

Update:

Let's say, you are passing many values in props and few values you want to override in component, so what you need to do here is, first apply all the props properties, then define the other properties. By this way, component properties will override the props properties.

Like this:

return <Checkbox
            {...this.props}                //first apply props values then other
            label="Label"
            checked={switched}
            onCheck={this.handleChange}                
       />

I ran into this problem when using two Mui Checkboxes which values depends on each other.

I had "parent state" which I tried to use within both of the checkboxes. I provided this state using context provider.

Solution

I solved the problem by initializing separate state const [checked, setChecked] = useState(false) inside both of the checkbox components. I did this to prevent "uncontrolled" component initialization.

To bind "checked" states to parent state, I defined a simple useEffect() function.

Like this:

export const DrugUsageStartCheckBox = () => {
    const { t } = useTranslation();
    // parent state can be used only if component is wrapped to context provider.
    const {state, dispatch} = useParentState();
    const [checked, setChecked] = useState(false)

    useEffect(() => {
        setChecked(state.checked)
    }, [state.checked])

    return (
            <Checkbox
                id={'my-checkbox'}
                checked={checked}
                onChange={(e) => {
                    dispatch({type: "toggleChecked"})
                }}
    ...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM