Reputation: 625
I have an app, where I need to manage focus on the inputs and for that purpose I use React ref
.
I have two inputs that I want to move into a separate component. Now they look like following:
<input
onChange={this.handleChangeOne}
ref={refOne => (this.refOne = refOne as HTMLInputElement)}
type="text"
/>
<input
onChange={this.handleChangeTwo}
ref={refTwo => (this.refTwo = refTwo as HTMLInputElement)}
type="text"
/>
I am having trouble to make the them work in a separate component while it involves passing down ref prop. I've tried something like this:
<InputBlock
handleChangeOne={() => this.handleChangeOne}
handleChangeTwo={() => this.handleChangeTwo}
refOne=(refOne => (this.refOne = refOne as HTMLInputElement)}
refTwo={refTwo => (this.refTwo = refTwo as HTMLInputElement)}
/>
And the components itself
class InputBlock extends React.Component<IProps> {
public render() {
return (
<React.Fragment>
<input
ref={refOne}
onChange={handleChangeOne}
type="text"
/>
<input
ref={refTwo}
onChange={handleChangeTwo}
type="text"
/>
</React.Fragment>
);
}
}
export default InputBlock;
For the sake of example I want handleChangeOne
to focus on input two, and handleChangeTwo
to focus on input one
Upvotes: 5
Views: 23523
Reputation: 332
For Functional Component:
import React,{useRef} from 'react';
const ParentComp = () => {
const parentDivRef = useRef<HTMLButtonElement>(null);
return(
<ChildButtonComp ref={parentDivRef}>Click Me</ChildButtonComp>
)
}
import React, { Ref, forwardRef,ReactNode } from "react";
const ChildButtonComp = forwardRef(
(props: { children: ReactNode }, ref: Ref<HTMLButtonElement>) => {
return <button ref={ref}>{props.children}</button>;
}
);
Upvotes: 0
Reputation: 30879
I don't know what went wrong for you, but the following is working for me:
import * as React from "react";
import * as ReactDOM from "react-dom";
class OuterComponent extends React.Component<{}, {}> {
refOne: null | HTMLInputElement = null;
refTwo: null | HTMLInputElement = null;
render() {
return <InputBlock
handleChangeOne={this.handleChangeOne}
handleChangeTwo={this.handleChangeTwo}
refOne={refOne => (this.refOne = refOne)}
refTwo={refTwo => (this.refTwo = refTwo)}
/>;
}
handleChangeOne = () => {
console.log("handleChangeOne", this.refOne, this.refTwo);
}
handleChangeTwo = () => {
console.log("handleChangeTwo", this.refOne, this.refTwo);
}
}
interface IProps {
refOne: React.Ref<HTMLInputElement>;
refTwo: React.Ref<HTMLInputElement>;
handleChangeOne: React.ChangeEventHandler<HTMLInputElement>;
handleChangeTwo: React.ChangeEventHandler<HTMLInputElement>;
}
class InputBlock extends React.Component<IProps> {
public render() {
return (
<React.Fragment>
<input
ref={this.props.refOne}
onChange={this.props.handleChangeOne}
type="text"
/>
<input
ref={this.props.refTwo}
onChange={this.props.handleChangeTwo}
type="text"
/>
</React.Fragment>
);
}
}
ReactDOM.render(<OuterComponent/>, document.getElementById("root"));
Upvotes: 9