PM: “Users need to agree to the XXX protocol in order to click the button, otherwise it will be grayed!!” Me: You’re right

This is a common requirement in projects, especially in THE H5 mobile terminal. Today I will talk about the code implementation process in detail.

React + Material – UI + typescript

The effect is as followsHere is the main code, the main logic is the checkbox and button button, the above text layout will not be described.

Due to the use of material- UI, so some component names and ANTD are different, we can draw a conclusion.

Part of the logic will be written in the comments!!

HTML

<Grid className={classes.checkboxItem}>
          <FormControlLabel
            control={
              <Checkbox
                classes={{
                  root: classes.radioRoot
                }}
                checked={checked}
                onChange={()= >{ if(checked===false){ setChecked(true) }else if (checked===true){ setChecked(false) } }} size="small" color="primary" />} label=" I have read and agree to the above instructions "/>
        </Grid>
        <div className={classes.bottomContainer}>
          <Fab
            variant="extended"
            color="primary"
            aria-label="add"
            className={classes.bottomLink}
            disabled={btndisabled}
            onClick={getCountDown}
            style={{opacity:bottonOpa,backgroundColor:bottonBgColor,color:bottonColor}}
          >
            <Avatar
              variant="square"
              className={classes.bottomLinkIcon}
              src={img1}
            />Apply now {visible?<>{` (${time}s)`}</>: ""}</Fab>
          </div>
      </Grid>
Copy the code

CSS

	bottomLink: {
      position:'fixed',
      bottom:10,
      left:0,
      height: theme.typography.pxToRem(48),
      width: theme.typography.pxToRem(350),
      boxShadow: "0px 2px 8px 0px Rgba (0, 127, 254, 0.3)",
      margin: `0 ${theme.typography.pxToRem(13)}`,
    },
    bottomLinkIcon: {
      width: 16,
      height: 19,
      marginRight: 8,
      marginTop: -2,
    },
    bottomContainer: {
      position: "fixed",
      bottom: 0,
      left: 0,
      right: 0,
      padding: "8px 12px",
    },
    checkboxItem:{
      position:'fixed',
      bottom:70,
      left:55,
    },
    radioRoot: {
      position: 'fixed',
      left: 10,},Copy the code

JS

1. Reference related component libraries

import React, {useState, useEffect}from "react"; 
import { useHistory } from 'react-router-dom';
import { makeStyles, Theme, createStyles } from '@material-ui/core/styles';
import { Typography, Grid , Avatar, Fab} from "@material-ui/core";
import Checkbox from '@material-ui/core/Checkbox';
import FormControlLabel from '@material-ui/core/FormControlLabel';
Copy the code

2. Define initial variables

let bottonOpa = 0.5; 
let bottonBgColor = '#007FFE';
let bottonColor = '#fff';

const img1 = require('@/assets/images/[email protected]')
Copy the code

3. React Hook in scenarios

  const history = useHistory();		// Click the back route to jump
  const [checked, setChecked] = useState(false);	// Check box status, unselected by default
  const [btndisabled, setBtndisabled] = useState(true);		// The button status is unclickable by default
  const [timerDisabled, setTimerDisabled] = useState(false); // Monitor time
  const [time, setTime] = useState(15);		// Count down to 15s
  const [visible, setVisible] = useState(true); // Button countdown copy
Copy the code

4. Events triggered by clicking a button

  const getCountDown = () = > {
    setTimerDisabled(true); 	// Start the countdown, and the countdown needs a series of listening events
    history.push('/nextPage')  	// Route to next page
  };
Copy the code

5. Listen time + check box

  useEffect(() = > {
    const timeChange = setTimeout(() = > {	// The initial time is 15s, and the countdown starts at 1s intervals
      setTime((oldTime) = > oldTime - 1); 
    }, 1000);
    if (timerDisabled) {	// Clear the timer if there is no time listening
      clearInterval(timeChange);
    }
    if(time === 0) {// When the countdown is 0
      clearInterval(timeChange);	// Clear the timer
      setVisible(false)		// The time text of the button is no longer displayed
    }
    if (time === 0 && checked === true) { 	// The countdown is 0, and the check box ☑️ is selected
      setBtndisabled(false)		// The button is clickable
      setVisible(false)			// The time text of the button is no longer displayed
      bottonOpa = 1			// The button does not need to be gray
      clearInterval(timeChange);  // Clear the timer
    }
    return () = >{
      clearInterval(timeChange)
    }
  }, [time, timerDisabled]);


  useEffect(() = >{
    if(checked === true && !time){	// The check box ☑️ is selected, and the time is 0
      setBtndisabled(false)		// The button is clickable
      bottonOpa = 1		// The button does not need to be gray
    }else {		// The checkbox is checked, but the time is still running
      setBtndisabled(true) 	// The button is not clickable
      bottonOpa = 0.5		// The button is dimmed
    }
  },[checked])
Copy the code

The whole operation process is complete.

An aside:

1) Why do I write so many variables to control CSS styles (buttons translucent and opaque)? Why don’t I just add the disabled property to the button?

Who wouldn’t? But Materi-Ui is his designer

By design, Disabled is as gray as the sky just cried…

This can not satisfy the aesthetic of our high-end foreign style products, so we can only use variable method (although a little tired), but I can give him what he wants!

2) Why not write the disabled style in the global CSS file?

Button_disabled {balabalabala}, just override the original style, but no!!

We can only change the basic attributes, such as root and input, so… If you successfully change the disabled attribute, please contact me as soon as possible!