Chrome自动填充导致文本字段标签和值的文本框冲突

bjp0bcyl  于 12个月前  发布在  Go
关注(0)|答案(2)|浏览(119)

在React中,自动完成Chrome值不会立即触发onChange事件。因此,在页面的初始加载期间,它会导致MUI TextField Label和实际值的冲突。如何解决此问题?

尝试了许多方法,InputLabelProps在Value上收缩也不起作用。https://stackoverflow.com/a/65070465/15435022

<StyledTextField
    fullWidth
    id="email"
    label="Email"
    size="medium"
    value={emailAddress}
    onChange={(e) => setEmailAddress(e.target.value)}
    error={emailError}
    InputLabelProps={{
      shrink: emailAddress != null && emailAddress != "" ? true : false,
    }}
    helperText={emailError ? "Please enter a valid email" : "Required"}
 />

尝试这种解决方案也会出现问题:执行const theme = createTheme({
Github资源:https://github.com/mui/material-ui/issues/14427#issuecomment-466054906

hpcdzsge

hpcdzsge1#

  • 就个人而言,我不认为果汁是值得挤压这与只是禁用收缩或自动完成登录,但没有人问我的意见,所以... *

据我所知,这比我们希望的更痛苦的原因是因为它最初是作为一种安全功能,以防止通过自动完成密码被盗,但一旦Chrome(等)取消了限制,React的去重复机制就接管了。这里有一些比我将要建议的稍微更像黑客的工作区,但是你可以决定你喜欢哪一个。
要避开这个问题,您可以为每个inputonAnimationStart事件添加一个处理程序,检查animationName是否为"mui-auto-fill",然后检查input是否有-webkit-autofill pseudo class,以查看浏览器是否自动填充了该字段。您还需要处理"mui-auto-fill-cancel"的情况,在这种情况下,表单是自动填充的,用户清除值(重置shrink)。
举例来说:

const [passwordHasValue, setPasswordHasValue] = React.useState(false);

// For re-usability, I made this a function that accepts a useState set function
// and returns a handler for each input to use, since you have at least two 
// TextFields to deal with.
const makeAnimationStartHandler = (stateSetter) => (e) => {
  const autofilled = !!e.target?.matches("*:-webkit-autofill");
  if (e.animationName === "mui-auto-fill") {
    stateSetter(autofilled);
  }

  if (e.animationName === "mui-auto-fill-cancel") {
    stateSetter(autofilled);
  }
};
...

<TextField
  type="password"
  id="password"
  inputProps={{
    onAnimationStart: makeAnimationStartHandler(setPasswordHasValue)
  }}
  InputLabelProps={{
    shrink: passwordHasValue
  }}
  label="Password"
  value={password}
  onChange={(e) => {
    setPassword(e.target.value);
    ...
  }}
/>

结果on load应显示为:

Updatewith cancel --允许用户在自动填充加载后清除表单字段,并重置标签:

zzwlnbp8

zzwlnbp82#

谢谢史蒂夫。效果很好。我根据你的回答为我的项目写了一个组件:

import {TextField} from "@mui/material";
import {useCallback, useState} from "react";

const AutoFillAwareTextField = ({onChange, inputProps, InputLabelProps, ...rest}) => {

    const [fieldHasValue, setFieldHasValue] = useState(false)
    const makeAnimationStartHandler = (stateSetter) => (e) => {
        const autofilled = !!e.target?.matches("*:-webkit-autofill");
        if (e.animationName === "mui-auto-fill") {
            stateSetter(autofilled);
        }

        if (e.animationName === "mui-auto-fill-cancel") {
            stateSetter(autofilled);
        }
    }

    const _onChange = useCallback((e) => {
        onChange(e.target.value);
        setFieldHasValue(e.target.value !== "")
    }, [onChange])

    return <TextField
        inputProps={{
            onAnimationStart: makeAnimationStartHandler(setFieldHasValue),
            ...inputProps
        }}
        InputLabelProps={{
            shrink: fieldHasValue,
            ...InputLabelProps
        }}
        onChange={_onChange}
        {...rest}
    />
}
export default AutoFillAwareTextField

相关问题