Reputation: 9165
I have this situation in my app: https://codesandbox.io/s/14mq9969j3
My goal is to be able to focus on input inside GrandChildInput
component by clicking on div in ChildInput
. However, when ChildInput
gets rendered, the value of this.childRef.current
is null
, and it remains so until I manually focus on input by clicking into it. After that, the value of current
is being assigned.
You can track this transformation in the console. The this.childRef.current
log appears once, but its value changes after manually focusing on input by clicking on it.
My end goal is to have the StyledGrandChildInput work this way, but as an intermediary step, I am trying to make the unstyled component work. I am able to achieve this result (with unstyled component) in my local project with:
But when it comes to working in CodeSandbox with the versions that are installed in the project through the link above, for some reason even focusing on non-styled GrandChildInput component does not work.
How can I make the app focus on GrandChildInput component when I click on div
of ChildInput?
Upvotes: 4
Views: 24257
Reputation: 4330
Please give React.forwardRef() a read.
This allows to pass refs from parent downwards as a secondary parameter (where the first parameter are the props). It doesn't help much in reverse however... that's what I'm currently struggling with lol...
Upvotes: 0
Reputation: 9165
To add up to @ShubhamKhatri's answer for those who is having difficulties performing the same operation, but when GrandChildInput is a styled-component
and the version of styled-component
is below 4
.
With his implementation, you might be getting Uncaught TypeError: _this.childRef.current.handleFocus is not a function
.
In this case, rename the ref
property on a styled-component to be innerRef
this way:
<div
onClick={() => this.childRef.current.handleFocus()}
style={{ border: "1px solid black", padding: 5 }}
>
click me
<StyledGrandChildInput
type="text"
disabled
focused
length={5}
innerRef={this.childRef} // change
/>
</div>
Upvotes: 0
Reputation: 281686
When you try try to assign the onClick handler to the div using the ref, it will try to immediately access handleFocus from ref, but since it not yet assigned to the input component. Its value will be null and hence you get that error.
As far as the value being printed, correct in the console, it has to do with how console evaluates the value. This answer
will provide more details on that
So in order to solve your problem, what you need to do is to call the handleFocus function by wrapping in another function so that its evaluated only on click like
<div
onClick={() => this.childRef.current.handleFocus()}
style={{ border: "1px solid black", padding: 5 }}
>
click me
<GrandChildInput
type="text"
disabled
focused
length={5}
ref={this.childRef}
/>
</div>
Also if you are wondering why your way did not work. Its because nothing caused the render method to be called again, so that the correct function was assigned to onClick after the ref has been assigned and available.
Upvotes: 6