0

我使用受控文本字段,以便监听该字段中值的变化,并在以大写或小写形式请求条目的情况下强制该值。

所以我必须使用组件状态的 value 属性。

不幸的是,如果我在另一个 Redux 组件中使用这个组件,并且想通过连接到 Redux 的全局状态的属性来更新这个字段,我不知道该怎么做。

如果我使用我的组件的属性来对我的受控字段进行赋值,那么在字段的 onChange 之后,我会丢失与条目相关的修改(因为我没有按值对状态进行赋值)。

如果我在受控字段的估值中使用状态,则根本不会检索 Redux 道具提供的值。有任何想法吗?

我的组件的简化代码片段:

import { TextField } from '@material-ui/core';
import React from 'react';
import { 
  MyInputProperties, 
  defaultInputFieldPropsValue
} from './MyInputProperties';
import { MyInputState } from './MyInputState';

export class MyInput
  extends React.Component<MyInputProperties, MyInputState> {

  static readonly VERSION: number = 100;

  public static defaultProps = defaultInputFieldPropsValue;

  constructor(props: MyInputProperties) {
    super(props);
    this.state = {
      ...this.state,
      value: this.props.value
    };
  }

  protected render(): JSX.Element {
    const {
      error,
      focused,
      helperText,
      label,
      required,
      type,
      textTransform,
      style,
      value: propValue
    } = this.props;

    const { value: stateValue } = this.state;

    const element = (
      <TextField
        inputProps={{ style: { textTransform: textTransform } }}
        id={this.id}
        disabled={this.isDisabled}
        error={error}
        focused={focused}
        helperText={helperText}
        label={label}
        onChange={this.handleChange.bind(this)}
        required={required}
        style={style}
        type={type}
        defaultValue={propValue}
        value={stateValue}
      />
    );

    return element;
  }

  private formatValue(value?: string): string | undefined {
    const { textTransform } = this.props;
    let curValue = value;
    if (curValue && textTransform) {
      if (textTransform === 'uppercase') {
        curValue = curValue.toUpperCase();
      } else if (textTransform === 'lowercase') {
        curValue = curValue.toLowerCase();
      }
    }
    return curValue;
  }

  /**
   * Callback fired when changing the value.
   * @param event Change event
   */
  private handleChange(event: React.ChangeEvent<HTMLInputElement>): void {
    const value = event.target.value;
    this.setState({ value: this.formatValue(value) });
  }
}
4

2 回答 2

0

您希望组件通过 props 获取和更改其值,而不是将值存储在本地状态中。这样组件就不需要知道或关心值是来自 redux 还是来自另一个组件的状态。

如果您愿意,您可以保留本地状态,但您希望props.value成为唯一的事实来源并在props.value更改时更新本地状态。

我建议您添加一个道具,该道具setValue将是一个void带有string. 当TextField更改时,我们将对新值应用正确的格式,然后setValue使用新的格式化值调用。

关于您的代码的一些旁注:

  • 您可以使用扩展运算符一次传递大量道具,TextField而不是单独分配它们
  • 您不应将元素分配给const element. 直接退货就行了。

这是一个作为函数组件的简单版本。该组件获取所有有效的 propsTextField并传递它们。我们对输入的每次更改都强制使用大小写,但请注意,我们不检查初始值的大小写,或者它是否由于外部因素而改变。

import React from "react";
import { TextField, TextFieldProps } from '@material-ui/core';

type MyInputProperties = TextFieldProps & {
  textTransform?: "uppercase" | "lowercase";
  setValue(value: string): void;
  value?: string;
}

export const CaseEnforcingInput = ({value = '', setValue, textTransform, ...props}: MyInputProperties) => {

  const formatValue = (value?: string): string | undefined => {
    let curValue = value;
    if (curValue && textTransform) {
      if (textTransform === 'uppercase') {
        curValue = curValue.toUpperCase();
      } else if (textTransform === 'lowercase') {
        curValue = curValue.toLowerCase();
      }
    }
    return curValue;
  }

  const handleChange = (event: React.ChangeEvent<HTMLInputElement>): void => {
    const value = event.target.value;
    setValue( formatValue(value) );
  }
  
  return (
    <TextField
      {...props} // pass though all other props
      onChange={handleChange}
      value={value}
      //inputProps={{ style: { textTransform: textTransform } }}
  />
  )
};

如果与格式不匹配,我们可以使用componentDidMount/useEffect来调用setValue格式正确的值。props.value我们还想检查何时props.textTransform更改。我们可以检查props.valueto 的变化,但我们需要小心谨慎,因为如果没有正确完成很容易创建无限循环。

于 2020-10-12T21:50:33.947 回答
0

对不起,是我搞砸了。我不需要在输入中存储状态。当我使用状态时,我的字段显示为我的道具中存在的值。突然我失去了用户输入......我很愚蠢。谢谢琳达的回答,这让我做出了反应。

于 2020-10-14T09:26:56.183 回答