How can I bind to a stateless refact component?

I am looking to create a stateless component that the input element can be checked by the parent component.

In my example below, I _emailAddress with a problem where the input ref never assigned to the parent _emailAddress private property.

When handleSubmit is called, this._emailAddress not undefined . Am I missing something or is there a better way to do this?

 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> ); 
+27
source share
4 answers

EDIT: Now you can with React Hooks. See the answer of Ante Gulin.

You cannot access React-like methods (e.g. componentDidMount , componentWillReceiveProps , etc.) for stateless components, including refs . Check out this discussion on GH for a complete convo.

The idea of ​​statelessness is that no instance (state) is created for it. Thus, you cannot attach ref , since there is no state to which it can be bound.

It is best to pass a callback when the component changes, and then assign this text to the parent state.

Or you can discard the stateless component altogether and use the regular class component.

From the documents ...

You cannot use the ref attribute on functional components because they have no instances. However, you can use the ref attribute inside the render function of the functional component.

 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> ); } 
+36
source

You can use useRef which is available since v16.7.0-alpha .

EDIT: You are invited to use Hooks in the production of 16.8.0 version 16.8.0 !

Hooks allow you to maintain state and handle side effects in functional components.

 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> </> ); } 

Read the Hooks API documentation for more information.

+30
source

I need something like this. To add to Brad's answer, you can pass the validation handler as a support, and then use the internal function to call the validation handler.

 function CustomTextInput({ validationHandler }) { // textInput must be declared here so the ref callback can refer to it let textInput = null; function handleClick() { validationHandler(textInput.value); } return ( <div> <input type="text" ref={(input) => { textInput = input; }} /> <input type="button" value="Validate the text input from a parent function" onClick={handleClick} /> </div> ); } 
+2
source

The value of your TextInput is nothing but the state of your component. So instead of getting the current value using a link (a bad idea in general, as far as I know), you can get the current state.

In the shortened version (without input):

 class Form extends React.Component { constructor() { this.state = { _emailAddress: '' }; this.updateEmailAddress = this.updateEmailAddress.bind(this); this.handleSubmit = this.handleSubmit.bind(this); } updateEmailAddress(e) { this.setState({ _emailAddress: e.target.value }); } handleSubmit() { console.log(this.state._emailAddress); } render() { return ( <form onSubmit={this.handleSubmit}> <input value={this.state._emailAddress} onChange={this.updateEmailAddress} /> </form> ); } } 
+1
source

Source: https://habr.com/ru/post/1261017/


All Articles