如何在React中附加无状态组件的ref?

dre*_*att 42 jsx typescript reactjs

我期待创建一个无状态组件,其输入可以由父元素验证.

在下面的示例中,我遇到了一个问题,即输入引用永远不会被分配给父的私有input属性.

什么时候ref叫,_emailAddresshandleSubmit.有什么我想念的,还是有更好的方法来做到这一点?

interface FormTestState {
    errors: string;
}

class FormTest extends React.Component<void, FormTestState> {
    componentWillMount() {
        this.setState({ errors: '' });
    }

    render(): JSX.Element {
        return (
            <main role='main' className='about_us'>             
                <form onSubmit={this._handleSubmit.bind(this)}>
                    <TextInput 
                        label='email'
                        inputName='txtInput'
                        ariaLabel='email'
                        validation={this.state.errors}
                        ref={r => this._emailAddress = r}
                    />

                    <button type='submit'>submit</button>
                </form>
            </main>
        );
    }

    private _emailAddress: HTMLInputElement;

    private _handleSubmit(event: Event): void {
        event.preventDefault();
        // this._emailAddress is undefined
        if (!Validators.isEmail(this._emailAddress.value)) {
            this.setState({ errors: 'Please enter an email address.' });
        } else {
            this.setState({ errors: 'All Good.' });
        }
    }
}

const TextInput = ({ label, inputName, ariaLabel, validation, ref }: { label: string; inputName: string; ariaLabel: string; validation?: string; ref: (ref: HTMLInputElement) => void }) => (
    <div>
        <label htmlFor='txt_register_first_name'>
            { label }
        </label>

        <input type='text' id={inputName} name={inputName} className='input ' aria-label={ariaLabel} ref={ref} />

        <div className='input_validation'>
            <span>{validation}</span>
        </div>
    </div>
);
Run Code Online (Sandbox Code Playgroud)

Ant*_*lin 67

您可以使用useRef从开始可用的hook v16.7.0-alpha

编辑:建议您从16.8.0发行版开始在生产中使用Hooks !

挂钩使您能够维护状态并处理功能组件中的副作用。

function TextInputWithFocusButton() {
  const inputEl = useRef(null);
  const onButtonClick = () => {
    // `current` points to the mounted text input element
    inputEl.current.focus();
  };
  return (
    <>
      <input ref={inputEl} type="text" />
      <button onClick={onButtonClick}>Focus the input</button>
    </>
  );
}
Run Code Online (Sandbox Code Playgroud)

Hooks API文档中了解更多信息

  • 为什么回答问题我会感到沮丧?我没有提倡在生产中使用,OP也没有提出建议。问题是您是否可以在无状态组件中使用Refs,答案是“是”,钩子可以做到这一点。 (7认同)
  • 它是`alpha`花花公子,请勿在生产中使用 (2认同)
  • @Jafarrezaei是的,钩子目前处于alpha状态,但肯定会被采用。 (2认同)
  • 它超出了alpha甚至在本地本机反应7u7 (2认同)

Bra*_*ugh 46

您无法访问做出反应等的方法(如componentDidMount,componentWillReceiveProps等)上的无状态组件,包括refs.查看有关GH的全部讨论的讨论.

无状态的想法是没有为它创建实例(状态).因此,你不能附加一个ref,因为没有状态可以附加引用.

您最好的选择是传递组件更改时的回调,然后将该文本分配给父级的状态.

或者,您可以完全放弃无状态组件并使用普通的类组件.

来自文档......

您可能不会在功能组件上使用ref属性,因为它们没有实例.但是,您可以在功能组件的render函数中使用ref属性.

function CustomTextInput(props) {
  // textInput must be declared here so the ref callback can refer to it
  let textInput = null;

  function handleClick() {
    textInput.focus();
  }

  return (
    <div>
      <input
        type="text"
        ref={(input) => { textInput = input; }} />
      <input
        type="button"
        value="Focus the text input"
        onClick={handleClick}
      />
    </div>
  );  
}
Run Code Online (Sandbox Code Playgroud)


Aru*_*mar 6

这已经很晚了,但我发现这个解决方案要好得多。注意它如何使用useRef以及如何在当前属性下使用属性。

function CustomTextInput(props) {
  // textInput must be declared here so the ref can refer to it
  const textInput = useRef(null);

  function handleClick() {
    textInput.current.focus();
  }

  return (
    <div>
      <input
        type="text"
        ref={textInput} />
      <input
        type="button"
        value="Focus the text input"
        onClick={handleClick}
      />
    </div>
  );
}
Run Code Online (Sandbox Code Playgroud)

有关更多参考检查反应文档