Reputation: 8594
I'm trying to access a component's specific child DOM node like this:
let targetChild = null;
React.Children.forEach(children, child => {
if (child.type.displayName === 'TargetElement') {
targetChild = child;
}
});
const targetEl = ReactDOM.findDOMNode(targetChild);
However, I keep getting the error:
Uncaught Error: Argument appears to not be a ReactComponent.
When I log out the typeof targetChild
I get object
. Does anyone know how to fix this? Thanks!
Upvotes: 2
Views: 3738
Reputation: 15656
In order to get the DOM element of a particular React component instance, you need to use the Callback Refs.
Here's a demo for you:
const children = ['Bob', 'Jeff', 'Kate'];
const TARGET_NODE = 'Jeff';
let jeffRef;
const setRef = (el, label) => {
if(label === TARGET_NODE) {
jeffRef = el;
}
}
const SampleApp = ({children}) => (
<ul>
{children.map((child, index) => (
<li key={index} ref={el => setRef(el, child)}>{child}</li>
))}
</ul>
)
ReactDOM.render(<SampleApp children={children}/>, document.querySelector("#app"))
console.log(jeffRef) // Should output: <li>Jeff</li>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="app"></div>
PS: In my opinion, accessing DOM elements can be avoided in most cases. You might want to reconsider doing that. You can control/update the element using component state instead.
Upvotes: 0
Reputation: 3558
Above all findDOMNode
should not be used
Also note that typeof null
is object
The problem is you are passing the React Element
instead of React Component's instance
read more about difference between React Element
vs React Component
vs React Component instance
https://reactjs.org/blog/2015/12/18/react-components-elements-and-instances.html
in short if UL
is a React Component
( either class component or function component ) then <UL />
is React element
Also note that you can use findDOMNode
only on Class Component
not the function component
The documentation seems a little misleading because it says
ReactDOM.findDOMNode(component)
notice it says Component
but I did some search and find out that you need to pass the component's instance
instead of component
for example following will work because this
will points to the component's instance
import React from "react";
import ReactDOM from "react-dom";
const UL = props => {
return <ul>{props.children}</ul>;
};
class List extends React.Component {
componentDidMount() {
console.log('printing', ReactDOM.findDOMNode(this));
}
render() {
return <li>this is targe element</li>;
}
}
export default function App() {
return (
<div className="App">
<UL>
<li>Hello CodeSandbox</li>
<List />
<li>Start editing to see some magic happen!</li>
</UL>
</div>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
but following will not work because we are passing a React element
instead of component's instance
import React from "react";
import ReactDOM from "react-dom";
class UL extends React.Component {
componentDidMount() {
let element = null;
React.Children.forEach(this.props.children, (child, index) => {
if (index === 1) {
console.log('logging child', child);
element = child;
}
});
console.log('printing', ReactDOM.findDOMNode(element));
}
render() {
return <ul>{this.props.children}</ul>;
}
};
class List extends React.Component {
render() {
return <li>this is targe element</li>;
}
}
List.displayName = 'TargetElement';
export default function App() {
return (
<div className="App">
<UL>
<li>Hello CodeSandbox</li>
<List />
<li>Start editing to see some magic happen!</li>
</UL>
</div>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
Upvotes: 3