代码之家  ›  专栏  ›  技术社区  ›  mettamyron

具有多用途的材质UI滑块单击时状态重复

  •  1
  • mettamyron  · 技术社区  · 1 年前

    我试图使用Material Ui滑块和useState创建字体大小和字体粗细预览器,但当我在单击第二个滑块后单击第一个滑块时,第一个滑块会重复。

    screenshot

    这是我的代码:

    import React from "react";
    import { withStyles, makeStyles } from "@material-ui/core/styles";
    import Slider from "@material-ui/core/Slider";
    import Typography from "@material-ui/core/Typography";
    
    import Container from "@material-ui/core/Container";
    import TextField from '@mui/material/TextField';
    
    const useStyles = makeStyles((theme) => ({
      root: {
        width: 300 + theme.spacing(3) * 2
      },
      margin: {
        height: theme.spacing(3)
      }
    }));
    
    const iOSBoxShadow =
      "0 3px 1px rgba(0,0,0,0.1),0 4px 8px rgba(0,0,0,0.13),0 0 0 1px rgba(0,0,0,0.02)";
    
    const marks = [
      {
        value: 0
      },
      {
        value: 25
      },
      {
        value: 50
      },
      {
        value: 75
      },
      {
        value: 100
      }
    ];
    
    const IOSSlider = withStyles({
      root: {
        color: "#3880ff",
        height: 2,
        padding: "15px 0"
      },
      thumb: {
        height: 28,
        width: 28,
        backgroundColor: "#fff",
        boxShadow: iOSBoxShadow,
        marginTop: -14,
        marginLeft: -14,
        "&:focus, &:hover, &$active": {
          boxShadow:
            "0 3px 1px rgba(0,0,0,0.1),0 4px 8px rgba(0,0,0,0.3),0 0 0 1px rgba(0,0,0,0.02)",
          // Reset on touch devices, it doesn't add specificity
          "@media (hover: none)": {
            boxShadow: iOSBoxShadow
          }
        }
      },
      active: {},
      valueLabel: {
        left: "calc(-50% + 12px)",
        top: -22,
        "& *": {
          background: "transparent",
          color: "#000"
        }
      },
      track: {
        height: 2
      },
      rail: {
        height: 2,
        opacity: 0.5,
        backgroundColor: "#bfbfbf"
      },
      mark: {
        backgroundColor: "#bfbfbf",
        height: 8,
        width: 1,
        marginTop: -3
      },
      markActive: {
        opacity: 1,
        backgroundColor: "currentColor"
      }
    })(Slider);
    
    export default function CustomizedSlider() {
      const classes = useStyles();
    
      const [userFontSize, setUserFontSize] = React.useState("1rem");
      const [userFontWeight, setUserFontWeight] = React.useState("300");
      const [sliderSizeTracker, setSliderSizeTracker] = React.useState(0);
      const [sliderWeightTracker, setSliderWeightTracker] = React.useState(999);
    
    
      const handleSizeChange = (e, newSizeValue) => {
        switch (newSizeValue) {
          case 0: {
            setUserFontSize("1rem");
            setSliderSizeTracker(0);
            break;
          }
          case 25: {
            setUserFontSize("1.19rem");
            setSliderSizeTracker(25);
            break;
          }
          case 50: {
            setUserFontSize("1.37rem");
            setSliderSizeTracker(50);
            break;
          }
          case 75: {
            setUserFontSize("1.55rem");
            setSliderSizeTracker(75);
            break;
          }
          case 100: {
            setUserFontSize("1.75rem");
            setSliderSizeTracker(100);
            break;
          }
          default: {
            break;
          }
        }
      };
    
      const handleWeightChange = (e, newWeightValue) => {
        switch (newWeightValue) {
          case 0: {
            setUserFontWeight("300");
            setSliderWeightTracker(0);
            break;
          }
          case 25: {
            setUserFontWeight("400");
            setSliderWeightTracker(25);
            break;
          }
          case 50: {
            setUserFontWeight("500");
            setSliderWeightTracker(50);
            break;
          }
          case 75: {
            setUserFontWeight("700");
            setSliderWeightTracker(75);
            break;
          }
          case 100: {
            setUserFontWeight("900");
            setSliderWeightTracker(100);
            break;
          }
          default: {
            break;
          }
        }
      };
    
      return (
        <Container maxWidth="sm" style={{ marginTop: "2em" }}>
          <div className={classes.root}>
            <Typography gutterBottom>Font Size Slider</Typography>
            <IOSSlider
              aria-label="Font Size Slider"
              key={sliderSizeTracker}
              defaultValue={sliderSizeTracker}
              marks={marks}
              step={25}
              onChangeCommitted={handleSizeChange}
              valueLabelDisplay="off"
            />
            <Typography gutterBottom>Font Weight Slider</Typography>
            <IOSSlider
              aria-label="Font Weight Slider"
              key={sliderWeightTracker}
              defaultValue={sliderWeightTracker}
              marks={marks}
              step={25}
              onChangeCommitted={handleWeightChange}
              valueLabelDisplay="off"
            />
            <div className={classes.margin} />
            <TextField
              sx={{ border: 'none', "& fieldset": { border: 'none' }, }}
              margin="normal"
              required
              fullWidth
              inputProps={{ style: { fontSize: `${userFontSize}`, fontWeight: `${userFontWeight}` } }}
              defaultValue="The quick brown fox jumps over the lazy dog"
              multiline
              rows={2}
            />
          </div>
        </Container>
      );
    }
    
    

    codesandbox

    我认为这与我使用useState的方式有关,但功能本身似乎是有效的。

    1 回复  |  直到 1 年前
        1
  •  0
  •   Drew Reese    1 年前

    正在删除 key 道具上 IOSSlider 组件似乎修复了沙盒中的问题。

    <IOSSlider
      aria-label="Font Size Slider"
      // key={sliderSizeTracker} // <-- remove this
      defaultValue={sliderSizeTracker}
      marks={marks}
      step={25}
      onChangeCommitted={handleSizeChange}
      valueLabelDisplay="off"
    />
    
    <IOSSlider
      aria-label="Font Weight Slider"
      // key={sliderWeightTracker} // <-- remove this
      defaultValue={sliderWeightTracker}
      marks={marks}
      step={25}
      onChangeCommitted={handleWeightChange}
      valueLabelDisplay="off"
    />
    

    沙盒中的另一个问题是,你正在使用React 18,但使用React 18之前的ReactDOM模式来渲染你的应用程序。应更新为以下内容:

    index.js

    import React from "react";
    import { createRoot } from "react-dom/client";
    import Demo from "./demo";
    
    const rootElement = document.getElementById("root");
    const root = createRoot(rootElement);
    
    root.render(<Demo />);