【问题标题】:Material UI this.state error for color background颜色背景的材质 UI this.state 错误
【发布时间】:2021-08-10 03:18:40
【问题描述】:

我的眼睛受伤了,我试图让滑块不仅可以改变按钮的半径,还可以改变颜色。

sandbox 成功更新半径。

Here is the code:
import React from "react";
import { makeStyles } from "@material-ui/core/styles";
import Grid from "@material-ui/core/Grid";
import Slider from "@material-ui/core/Slider";
import Input from "@material-ui/core/Input";
import Button from "@material-ui/core/Button";
import reactCSS from "reactcss";
import { SketchPicker } from "react-color";

const useStyles = makeStyles((theme) => ({
  root: {
    "& > *": {
      margin: theme.spacing(1)
    }
  },
  Button: {
    width: 150,
    height: 50,
    borderRadius: "var(--borderRadius)"
  }
}));

export default function InputSlider() {
  const classes = useStyles();
  const [value, setValue] = React.useState(30);
  const handleSliderChange = (event, newValue) => {
    setValue(newValue);
  };
  const handleInputChange = (event) => {
    setValue(event.target.value === "" ? "" : Number(event.target.value));
  };
  const handleBlur = () => {
    if (value < 0) {
      setValue(0);
    } else if (value > 30) {
      setValue(30);
    }
  };
  return (
    <div className={classes.root}>
      <style>
        {`:root {
          --borderRadius = ${value}px;
        }`}
      </style>
      <Button
        style={{ borderRadius: value }}
        variant="contained"
        color="primary"
        value="value"
        onChange={handleSliderChange}
        className={classes.Button}
      >
        Fire laser
      </Button>
      <Grid container spacing={2}>
        <Grid item xs>
          <Slider
            value={typeof value === "number" ? value : 0}
            onChange={handleSliderChange}
            aria-labelledby="input-slider"
          />
        </Grid>
        <Grid item>
          <Input
            value={value}
            margin="dense"
            onChange={handleInputChange}
            onBlur={handleBlur}
            inputProps={{
              step: 10,
              min: 0,
              max: 24,
              type: "number"
            }}
          />
        </Grid>
      </Grid>
    </div>
  );
}

现在我正在努力使用color picker 来更改按钮的背景颜色,并最终更改字体颜色。

我收到了我的this.state 的错误消息。建议?

这是一个不同的沙盒,它正在进行中并且有错误消息 - https://codesandbox.io/s/material-demo-forked-l35qy?file=/demo.js

这是带有错误消息的代码:

import React from "react";
import { makeStyles } from "@material-ui/core/styles";
import Grid from "@material-ui/core/Grid";
import Slider from "@material-ui/core/Slider";
import Input from "@material-ui/core/Input";
import Button from "@material-ui/core/Button";
import reactCSS from "reactcss";
import { SketchPicker } from "react-color";

const useStyles = makeStyles((theme) => ({
  root: {
    "& > *": {
      margin: theme.spacing(1)
    }
  },
  Button: {
    width: 150,
    height: 50,
    borderRadius: "var(--borderRadius)",
    background: `rgba(${this.state.color.r}, ${this.state.color.g}, ${this.state.color.b}, ${this.state.color.a})`
  },
  color: {
    width: "36px",
    height: "14px",
    borderRadius: "2px",
    background: `rgba(${this.state.color.r}, ${this.state.color.g}, ${this.state.color.b}, ${this.state.color.a})`
  },
  swatch: {
    padding: "5px",
    background: "#fff",
    borderRadius: "1px",
    display: "inline-block",
    cursor: "pointer"
  },
  popover: {
    position: "absolute",
    zIndex: "2"
  },
  cover: {
    position: "fixed",
    top: "0px",
    right: "0px",
    bottom: "0px",
    left: "0px"
  }
}));

export default function InputSlider() {
  const classes = useStyles();
  const [value, setValue] = React.useState(30);
  const handleSliderChange = (event, newValue) => {
    setValue(newValue);
  };
  const handleInputChange = (event) => {
    setValue(event.target.value === "" ? "" : Number(event.target.value));
  };
  const handleBlur = () => {
    if (value < 0) {
      setValue(0);
    } else if (value > 30) {
      setValue(30);
    }
  };
  const handleClick = () => {
    this.setState({ displayColorPicker: !this.state.displayColorPicker });
  };

  const handleClose = () => {
    this.setState({ displayColorPicker: false });
  };

  const handleChange = (color) => {
    this.setState({ color: color.rgb });
  };
  return (
    <div className={classes.root}>
      <style>
        {`:root {
          --borderRadius = ${value}px;
        }`}
      </style>
      <Button
        style={{ borderRadius: value }}
        variant="contained"
        color="primary"
        value="value"
        onChange={handleSliderChange}
        className={classes.Button}
      >
        Fire laser
      </Button>
      <Grid container spacing={2}>
        <Grid item xs>
          <Slider
            value={typeof value === "number" ? value : 0}
            onChange={handleSliderChange}
            aria-labelledby="input-slider"
          />
        </Grid>
        <Grid item>
          <Input
            value={value}
            margin="dense"
            onChange={handleInputChange}
            onBlur={handleBlur}
            inputProps={{
              step: 10,
              min: 0,
              max: 24,
              type: "number"
            }}
          />
        </Grid>
      </Grid>
      <div>
        <Button style={useStyles.color}></Button>

        <div style={useStyles.swatch} onClick={this.handleClick}>
          <div style={useStyles.color} />
        </div>
        {this.state.displayColorPicker ? (
          <div style={useStyles.popover}>
            <div style={useStyles.cover} onClick={this.handleClose} />
            <SketchPicker
              color={this.state.color}
              onChange={this.handleChange}
            />
          </div>
        ) : null}
      </div>
    </div>
  );
}

【问题讨论】:

    标签: reactjs button material-ui background-color color-picker


    【解决方案1】:

    你不能在 useStyles 中使用状态,因为你只能访问主题而不是任何道具。您应该改用 makeStyles 调用,因为这至少可以让您传入一些道具。这已经在这里得到了回答,并且有一个很好的例子。

    Passing props to material UI style

    另一个问题是您使用的是基于功能的组件,其中状态的编写方式不同。我已经使用 useState 钩子为你重写了它,所以希望这至少可以让颜色使用。

    export default function InputSlider() {
      const classes = useStyles();
      const [value, setValue] = React.useState(30);
      const [color, setColor] = React.useState({ background: "#fff" });
    
      const handleSliderChange = (event, newValue) => {
        setValue(newValue);
      };
      const handleInputChange = (event) => {
        setValue(event.target.value === "" ? "" : Number(event.target.value));
      };
      const handleBlur = () => {
        if (value < 0) {
          setValue(0);
        } else if (value > 30) {
          setValue(30);
        }
      };
      const handleClick = (color) => {
        setColor(color);
      };
    
      const handleClose = () => {
        setColor({ displayColorPicker: false });
      };
    
      const handleChange = (color) => {
        setColor(color);
      };
      return (
        <div className={classes.root}>
          <style>
            {`:root {
              --borderRadius = ${value}px;
            }`}
          </style>
          <Button
            style={{ borderRadius: value }}
            variant="contained"
            color="primary"
            value="value"
            onChange={handleSliderChange}
            className={classes.Button}
          >
            Fire laser
          </Button>
          <Grid container spacing={2}>
            <Grid item xs>
              <Slider
                value={typeof value === "number" ? value : 0}
                onChange={handleSliderChange}
                aria-labelledby="input-slider"
              />
            </Grid>
            <Grid item>
              <Input
                value={value}
                margin="dense"
                onChange={handleInputChange}
                onBlur={handleBlur}
                inputProps={{
                  step: 10,
                  min: 0,
                  max: 24,
                  type: "number"
                }}
              />
            </Grid>
          </Grid>
          <div>
            <Button style={useStyles.color}></Button>
    
            <div style={useStyles.swatch} onClick={handleClick}>
              <div style={useStyles.color} />
            </div>
            {color ? (
              <div style={useStyles.popover}>
                <div style={useStyles.cover} onClick={handleClose} />
                <SketchPicker color={color} onChange={handleChange} />
              </div>
            ) : null}
          </div>
        </div>
      );
    }
    

    【讨论】:

      【解决方案2】:

      @RichardHpa 是正确的,您无法访问 makeStyles 中的状态,并且您混淆了类组件和功能组件。在你的情况下,你应该一直使用useState()

      您已经有了如何设置边框半径的示例,因此您可以复制该流程以在您的背景颜色中使用它,直接在 Button 上设置样式。

      这里是代码框:

      https://codesandbox.io/s/material-demo-forked-djh78?file=/demo.js

      <Button
          style={{
              borderRadius: value,
              background: `rgba(${color.r}, ${color.g}, ${color.b}, ${color.a})`
      
              // may need another color picker for text coloe. otherwise, bg color will be the same as text color.
              // color: `rgba(${color.r}, ${color.g}, ${color.b}, ${color.a})`
          }}
          variant="contained"
          color="primary"
          value="value"
          onChange={handleSliderChange}
          className={classes.Button}
      >
      

      无需为我评分,@RichardHpa 值得称赞。

      【讨论】:

      • 谢谢@mic-fung 和@richard-hpa!
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-03-30
      • 1970-01-01
      • 2018-06-11
      • 2019-07-25
      • 2018-03-02
      相关资源
      最近更新 更多