【问题标题】:Material UI Custom TextField state issue in ReactReact 中的 Material UI 自定义 TextField 状态问题
【发布时间】:2021-09-28 17:49:18
【问题描述】:

一位同事(在 React 方面比我更有经验)围绕 mui 的 TextField 控件编写了这个反应包装组件,但它没有像我预期的那样工作,但我不知道为什么。所以我最终创建了一个沙箱(下面的链接)来使用原生沙箱来查看它是否有效。

我想知道的是,为什么包装器在安装消费者组件时不显示数据,而本机 mui 文本字段却显示?当 Example.tsx 加载时,本机 mui 文本字段按预期显示 json 中的数据。当您选择英语或西班牙语时,它会根据所选语言显示该状态的内容(如果没有该语言的数据,它会显示为空白,应该如此)。

自定义文本字段包装器没有此行为。它开始是空白的。当您更改语言时,它也不会显示数据。我刚开始使用 React,所以我可能会遗漏一些东西,但我至少希望这种行为是相同的。

您可以注释掉沙盒中的一个或其他文本字段以单独查看它们,如果这样可以减少混乱。

但这是包装器组件的代码。就 react 中的文本字段行为而言,是否有任何异常或不正确的地方?

import * as React from "react";
import {
  TextField as MaterialTextField,
  Typography,
  makeStyles
} from "@material-ui/core";

const useStyles = makeStyles({
  textField: {
    width: (props) => (props as TextFieldStyleProps).textFieldWidth + "px",
    "& input": {
      height: ".6rem"
    }
  }
});

export type TextFieldChangeHandler = (
  event: React.ChangeEvent<HTMLInputElement>
) => any;

type TextFieldStyleProps = {
  textFieldWidth: number;
};

export interface TextFieldProps {
  id?: string;
  label: string;
  text: string;
  width: number;
  disabled?: boolean;
  onChangeHandler: TextFieldChangeHandler;
}

const CustomTextField = (props: TextFieldProps) => {
  const {
    label,
    text,
    width,
    onChangeHandler,
    disabled,
    id = "textFieldDefault"
  } = props;
  const classes = useStyles({ textFieldWidth: width });
  const [value, setValue] = React.useState<string>(text);

  const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
    setValue(event.target.value);
    onChangeHandler(event);
  };

  return (
    <div>
      <div>
        <Typography
          id={"text-field-label-" + label}
          component="label"
          htmlFor={id}
          variant="caption"
        >
          {label}
        </Typography>
      </div>
      <MaterialTextField
        id={id}
        onChange={handleChange}
        className={classes.textField}
        variant="outlined"
        margin="normal"
        size="small"
        value={value}
        disabled={disabled}
      />
    </div>
  );
};

链接到带有不同行为示例的代码框:sanbox

【问题讨论】:

    标签: reactjs material-ui


    【解决方案1】:

    那是因为您的customField 的设置方式,您无法控制状态。您只能将初始值传递给它。然后value 状态在customField 内部声明,不再监听text 的变化。因此,当父组件挂载时,文本值是一个空字符串,它将作为初始值传递给useState,并且不再反映进一步的更改。解决此问题的一种方法是添加一个 useEffect 来检测 text 的更改并在 customField 组件中使用它更新值,如下所示:

      React.useEffect(() => {
        setValue(text);
      }, [text]);
    

    the working sandbox

    【讨论】:

    • 好的,有道理。所以基本上这是设置的方式,将文本输入其中的唯一方法是传递一次。然后它只能通过击键来改变。不过,我想不出你为什么要这样。大概只是疏忽。非常感谢,真的很有帮助。
    • 我也想不出任何好的理由。关于你的同事,我得说这只是一个奇怪的设计和抽象,除了混乱之外没有任何好处。你要么想要一个受控组件,在这种情况下你想将值设置为你的本地状态变量(你不能在这里做)或者你想要一个不受控制的组件,在这种情况下你不需要保留这个值处于一个状态并为它编写一个 onChange 处理程序
    猜你喜欢
    • 2019-08-30
    • 1970-01-01
    • 2021-11-14
    • 2019-12-27
    • 2020-07-30
    • 2020-07-18
    • 2020-06-29
    • 2017-03-01
    • 2020-09-15
    相关资源
    最近更新 更多