How to get a child's components DOMNode in ReactJS - reactjs

What is the current way to get a DOMNode in ReactJS from a child's component ?
...
this.refs.component.getDOMNode() // do not work anymore
React.findDOMNode(this.refs.component) // do also not work anymore
...
When access this.refs.component I just get the Component back but I need the rendered DOMNode. This DOMNode is needed by me for example to get the scrollTop value of the Element. These values are not available in the Component at it selfs in this.refs.component.
Edit/Answer
Someone posted an answer which was correct but - I dont know why - he/she deleted the post.
So the correct answer is to use ReactDOM.findDOMNode();
Reference:
https://facebook.github.io/react/docs/react-dom.html#finddomnode
This works perfectly for my usecase.

According to the Change Log
this.getDOMNode() is now deprecated and ReactDOM.findDOMNode(this) can
be used instead. Note that in the common case, findDOMNode is now
unnecessary since a ref to the DOM component is now the actual DOM
node.
The this.refs.component.getDOMNode() is no longer to use anymore. You can use ReactDOM.findDOMNode(this.refs.component) as what I mentioned in the comments instead.

Related

Alternative to Reactdom.render and unmountComponentAtNode in react18

Important note:
I am aware of createRoot and root.unmount()! Unfortunately (If I understand this correctly) they should be used just once in the application for mounting the react application.
Problem description:
In our app we have a modal component that is rendered dynamically and added to the body of the html via ReactDOM.render(). When this modal is hidden, we unmountComponentAtNode().
Unfortunately, after upgrading to react18, unmountComponentAtNode becomes deprecated and the new unmount is (in my understanding) for the root only. The same problem is about if I try to modify the ReactDOM.Render() for createRoot. Then we would have 2 roots in the app which is wrong.
What is the proper way to attach the modal to the body element (next to root!) and unmount it after it should be destroyed? The implementation is a little bit "weird" (partially in jsx, partially not...) and I would like to avoid refactoring the whole component as there will be a lot of refactoring already in the code... So I would like to focus on refactoring this component (into jsx one) later. Now I have to figure out only the rendering / unmounting. I have been thinking about using Portals, but anyway I have to create that elements somehow and render them into the DOM where portals does not help me a lot.
Calling the createRoot and then render on the root in this modal component fires an error You are calling ReactDOMClient.createRoot() on a container that has already been passed to createRoot() before. Instead, call root.render() on the existing root instead if you want to update it. which is obvious. But there is no "useRoot()" hook or anything like that. Should I store the returned object (root) in some context or somewhere to use it later? Or what should be the best option to call the render? :/
I know how I should do that with classical functional component... But maybe there is some way that I can just refactor a piece of the code instead of the whole component and all its usecases. Maybe there is something I am not aware of (there is definitely thousands of things I am not aware of :D) that should simplify my life...
function modal() {
return (
<div>
...
</div>
)
}
Modal.show = () => {
modalEl = document.createElement('div');
util.destroy(el) => {
ReactDOM.unmountComponentAtNode(el);
el.remove();
}
const childs = props.childs;
REactDOM.render(childs, modalEl);
}
When I was thinking about portals, I thought I will just rewrite the last line of ReactDOM.render to portal like createPortal(childs, modalEl), unfortunately this does not render anything (except modalEl, but no childs inside). The childs are of type ReactNode (using typescript) and they are not empty (because of ReactDOM.render works without any problem).

How to hide or remove an element onClick in React?

I am trying to hide an element 'GorillaSurfIn' after I click on it.
But also it should fire the 'setShouldGorillaSurfOut' to 'true'. The second part works, but after I added this function:
function hideGorillaSurfIn() {
let element = document.getElementById('gorilla-surf-in');
ReactDOM.findDOMNode(element).style.display =
this.state.isClicked ? 'grid' : 'none';
}
After I click, the code falls apart.
Once I click, the element should be hidden/removed till the next time the App restarts.
Here is the Code Sandbox Link for further explanation.
I am open to any solutions, but also explanations please, as I am still fresh in learning React.
I have changed your code a bit to make it work. You can make further changes according to your need. A few things that I would like to add: -
You should avoid using findDOMNode (in most cases refs can solve your problem) as there are certain drawbacks associated with findDOMNode, such as the react's documentation states "findDOMNode cannot be used with functional components".
I've used refs (forward ref in this case) to make it work.
GorillaSurfIn was called twice, so there were two Gorilla gifs on the screen with same IDs. Not sure if that was the intended behaviour but each element should have unique ID.
Check out the code sandbox.

Weird interaction 'react-virtualize'd working with 'react-sortable-hoc'

https://codesandbox.io/s/qYEvQEl0
So I wrote a demo myself that didn't work compare to one sample that works, the only difference being one props for <List/>
rowHeight={({ index }) => 50}
rowHeight={50}
I use the latter way ofc. And it is not working. Why?
Answer copied from the duplicate GitHub issue you filed ;)
This creates a new function prop each time you render:
rowHeight={({ index }) => 50}
The prop-change is sufficient to trigger a re-render of the child component even if no other properties changed. In the second example above, no props change at all and so List doesn't know it needs to re-render. (Check out the section on "pure components" in the docs for more info.)
In this case, you could pass a small attribute that changes each time sort order changes (eg an incremented counter) to let the component know to re-render. You could also call forceUpdate.

react willReceiveProps workaround for external library

I'm using a react datepicker component that can be found here. The component is pretty great except for what appears to be an oversight: it does not implement willReceiveProps.
To expound, I create the datpicker as below:
<DateField
dateFormat= { dateFormat}
forceValidDate={true}
defaultValue={startDate || ''}
onChange={this.handleChange.bind(null, 'start_date')}
id="start"
>
<DatePicker
navigation={true}
locale="en"
forceValidDate={true}
highlightWeekends={true}
highlightToday={true}
weekNumbers={true}
weekStartDay={0}
/>
</DateField>
Note above that there is a prop defaultValue which I pass startDate. Now, startDate can and does change for reasons that are sometimes external to the component. That value is passed during a new render() action as per usual. According to react philosophy this shouldn't be a problem.
However, it appears to me as if the value from defaultValue is only ever read once inside DateField. It is read as this.props.defaultValue. Anyone who has ever built a component relying on props should quickly recognize this is a problem. It means that when the prop is changed the new value will not be used.
Because this is a library, I cannot simply implement willReceiveProps. Does anyone know of a good workaround to get this component to either completely reset on a render or some other strategy to deal with what seems to be a big design problem?
They follow the same standards as the <input> component. defaultValue is read only once but there is also value that can be set externally. There is no need for them to use willReceiveProps.
In short, use value instead of defaultValue.
See Uncontrolled Components in React
PS: I am looking a bit into the code and it seems there are also properties text and date apart from value. Since the code (and documentation) has been removed from github, I won't inspect what is the difference between those props.

React.js how to call child component method without using refs?

I have an unusual case. Let say, I have a form. When the user clicks the "save" button I need to trigger a component's method to convert draft.js content to HTML. Normally I just use refs to get access to child and call any method. But in my case draft component is inside render method of react-router v4 and appears only when URL match pattern.
This is a hindrance cuz when I define ref
<Match pattern={'/info'} render={(props)=> <Draft_Editor ref='editor' />} />
parent component doesn't have this 'editor' in refs. What can i do to call method on from parent ?
One way is as follows.
1) Find the DOM node for the parent element using:
var parentDOM = ReactDOM.findDOMNode(parentCompInstance);
2) Find the DOM node for the child element, using:
var childDOM = parentDOM.children[0]; // or something like this, depending on html hierarchy
3) Find the React component instance for that child DOM node, using the solution mentioned here: React - get React component from a child DOM element?
I found solution for my case. Unfortunate, the solution is using ref but it performs it with other approach. Instead of making this ref='editor' I did this ref={(draft) => this.aboutEditor = draft}. This editor will be available as this.aboutEditor.
When i operated with ref as string it did't works. But it works fine as callback function.

Resources