
[英]Reactjs: Can I access a ref in stateless component's event handler?
[英]How can I attach to a stateless component's ref in React?
我希望创建一个无状态组件,其input
元素可以由父组件验证。
在下面的示例中,我遇到了一个问题,即从未将输入ref
分配给父级的私有_emailAddress
属性。
当handleSubmit
被调用时, this._emailAddress
是undefined
。 有什么我遗漏的,还是有更好的方法来做到这一点?
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>
);
您可以使用自v16.7.0-alpha
以来可用的useRef
钩子。
编辑:从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>
</>
);
}
在Hooks API 文档中阅读更多内容
编辑:您现在可以使用 React Hooks。 请参阅 Ante Gulin 的回答。
您无法在无状态组件(包括refs
)上访问类似 React 的方法(例如componentDidMount
、 componentWillReceiveProps
等)。 查看这个关于 GH 的讨论以获得完整的会议。
无状态的想法是没有为其创建实例(状态)。 因此,您不能附加ref
,因为没有要附加 ref 的状态。
最好的办法是在组件更改时传入回调,然后将该文本分配给父级的状态。
或者,您可以完全放弃无状态组件并使用普通的类组件。
您不能在功能组件上使用 ref 属性,因为它们没有实例。 但是,您可以在功能组件的渲染函数中使用 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>
);
}
这已经很晚了,但我发现这个解决方案要好得多。 注意它如何使用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>
);
}
有关更多参考检查反应文档
TextInput 的值只不过是组件的状态。 因此,您可以获取当前状态,而不是使用引用获取当前值(一般来说是个坏主意,据我所知)。
精简版(不打字):
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>
);
}
}
您还可以通过一些管道将 refs 导入到功能组件中
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 } />
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.