Ich möchte eine zustandslose Komponente erstellen, deren input
Element von der übergeordneten Komponente überprüft werden kann.
In meinem Beispiel unten stößt ich auf ein Problem, bei dem die Eingabe ref
niemals dem Privateigentum des Elternteils zugewiesen wird _emailAddress
.
Wann handleSubmit
heißt, this._emailAddress
ist undefined
. Fehlt mir etwas oder gibt es einen besseren Weg, dies zu tun?
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>
);
reactjs
typescript
jsx
Drawwyatt
quelle
quelle
console.log
Ihrer Ref-Funktion ein hinzu, um zu sehen, ob es aufgerufen wirdAntworten:
EDIT: Sie können jetzt mit React Hooks. Siehe die Antwort von Ante Gulin.
Sie können keinen Zugriff reagieren wie Methoden (wie
componentDidMount
,componentWillReceiveProps
usw.) auf stateless Komponenten, einschließlichrefs
. Schauen Sie sich diese Diskussion über GH an, um die vollständige Convo zu erhalten.Die Idee von zustandslos ist, dass keine Instanz dafür erstellt wurde (Status). Daher können Sie kein a anhängen
ref
, da es keinen Status gibt, an den der ref angehängt werden kann.Am besten übergeben Sie einen Rückruf, wenn sich die Komponente ändert, und weisen diesen Text dann dem Status der Eltern zu.
Oder Sie können ganz auf die zustandslose Komponente verzichten und eine normale Klassenkomponente verwenden.
Aus den Dokumenten ...
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> ); }
quelle
ref={input => innerRef(input)}
an die übergeordnete Komponente übergeben .innerRef={input => this.customInputRef = input}
Sie können einen
useRef
Haken verwenden, der seitdem verfügbar istv16.7.0-alpha
.EDIT: Wir empfehlen Ihnen, Hooks ab
16.8.0
Veröffentlichung in der Produktion zu verwenden !Mit Hooks können Sie den Status beibehalten und Nebenwirkungen in Funktionskomponenten behandeln.
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> </> ); }
Weitere Informationen finden Sie in der Dokumentation zur Hooks-API
quelle
Der Wert Ihres TextInput ist nichts anderes als ein Status Ihrer Komponente. Anstatt den aktuellen Wert mit einer Referenz abzurufen (schlechte Idee im Allgemeinen, soweit ich weiß), können Sie den aktuellen Status abrufen.
In einer reduzierten Version (ohne Eingabe):
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> ); } }
quelle
ref
. Ich kaufe mir total, dass das, was ich versuche, hier nicht möglich ist, aber würde es Ihnen etwas ausmachen, einen Artikel zu erklären oder darauf zu verweisen, der erklärt, warum die Verwendungref
im Allgemeinen eine schlechte Idee ist?Das ist spät, aber ich fand diese Lösung viel besser. Achten Sie darauf, wie useRef verwendet wird und wie Eigenschaften unter der aktuellen Eigenschaft verfügbar sind .
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> ); }
Für weitere Referenzprüfungen reagieren Sie auf Dokumente
quelle
Sie können auch Refs in funktionale Komponenten mit ein wenig Sanitär bekommen
import React, { useEffect, useRef } from 'react'; // Main functional, complex component const Canvas = (props) => { const canvasRef = useRef(null); // Canvas State const [canvasState, setCanvasState] = useState({ stage: null, layer: null, context: null, canvas: null, image: null }); useEffect(() => { canvasRef.current = canvasState; props.getRef(canvasRef); }, [canvasState]); // Initialize canvas useEffect(() => { setupCanvas(); }, []); // ... I'm using this for a Konva canvas with external controls ... return (<div>...</div>); } // Toolbar which can do things to the canvas const Toolbar = (props) => { console.log("Toolbar", props.canvasRef) // ... } // Parent which collects the ref from Canvas and passes to Toolbar const CanvasView = (props) => { const canvasRef = useRef(null); return ( <Toolbar canvasRef={canvasRef} /> <Canvas getRef={ ref => canvasRef.current = ref.current } /> }
quelle