Invariant Violation when using Link component in a dynamic menu - reactjs

I'm building a Menu component which renders a list of links which are created using the react-router Link component.
This is the code which renders each item of the menu:
<li
style={{opacity: this.props.isDragging ? 0 : 1}}
className="list">
<Link to={ this.props.list.url }
activeClassName="active"
className={ this.props.owner && 'draggable'}>
<span>{ this.props.list.title }</span>
{ this.props.owner ?
<div className="list-controls">
<span className="glyphicon
glyphicon-pencil"
aria-hidden="true"
onClick={this.setEditMode.bind(this, true)}>
</span>
<span className="glyphicon
glyphicon-remove"
aria-hidden="true"
onClick={this.deleteList.bind(this)}></span>
</div> : null
}
</Link>
</li>;
The menu is dynamic. This means that navigating to another url may re-render the menu with a different list of links. The problem is that when the menu is re-rendered, I get the following exception:
Uncaught Error: Invariant Violation: findComponentRoot(..., .0.0.0.4.$12.0): Unable to find element. This probably means the DOM was unexpectedly mutated (e.g., by the browser), usually due to forgetting a '<tbody>' when using tables, nesting tags like '<form>, <p>, or <a>', or using non-SVG elements in an <svg>' parent. Try inspecting the child nodes of the element with React ID ``.
I've checked that the .0.0.0.4.$12.0 element is the <a> tag generated by the Link component in the first render.
I've also checked that if I don't use the Link component (and, for example, use a simple <a> tag instead), the exception goes away. Any thoughts?
UPDATE: Apparently the error showed up when I started using react-router-redux (formerly redux-simple-router).

I ran into the same issue on a project using redux-simple-router (now react-router-redux) and was able to fix it by changing which lifecycle methods I was using to dispatch actions (which I was using to rerender a component with different <Link> components).
I created a reduced example in a gist which I got working with this revision.
In the gist there is a <Page> component which dispatches a SYNC action immediately and then a DONE action after 100ms which changes render() to show a loading indicator. Once loaded, the component was rendering some conditional elements, and one of them was a <Link> which was causing the same Invariant Violation.
Originally I was dispatching the actions from within the page's componentWillReceiveProps lifecycle method. When I changed it to componentDidUpdate the error went away. Here's the relevant code that I changed:
- componentWillReceiveProps(nextProps) {
- if (nextProps.params.param !== this.props.params.param) {
- nextProps.dispatch(fetch())
- }
- }
+ componentDidUpdate(prevProps) {
+ if (prevProps.params.param !== this.props.params.param) {
+ this.props.dispatch(fetch())
+ }
+ }
On a side note, I noticed that the error wasn't exclusive to rerendering <Link> components. I was able to recreate the same error when using any element (like a <span> or <a>) with an onClick handler).

Related

Adding a Link tag to a list of mapped values in next.JS

I am using Next.js and I am trying to add a link tag to each mapped value but I am getting the error listed below:
Unhandled Runtime Error
Error: Multiple children were passed to with href of /genrepage/Action/28 but only one child is supported https://nextjs.org/docs/messages/link-multiple-children
Open your browser's console to view the Component stack trace.
How would I correct my code to get around this issue. The mapped element returns an object with a name and an id. I feel the error is in the actual line with Link but I am not sure.
My code is pasted below
return (
<div className=" text-red-300;">
{mygenres.genres.map((elem) => (
<Link href={`/genrepage/${elem.name}/${elem.id}`}>
<button
onClick={() => {
setMyselectedgenre(elem);
}}
>
{elem.name}
</button>
</Link>
))}
</div>
);
and my relevant routing structure is
/genrepage
[genre].js
[id].js
When the user clicked the button, it will be meanless routing so define a route object inside your mygenres.genres object. Such as;
{
...,
route:"/3",
}
It will be easy to handle and already you're using id to route

Warning: FindNodeDom is deprecated in Strictmode when using Collapse (from react-bootstrap)

I am having an issue with this code in my React project. It would show a div with a warning about filenames to upload.
<Collapse in={this.state.open} id={"z-hover"}>
<div>
<ul>
{ FilesAllowed.files.map((fileName, index) => {
return <li key={index}>{fileName}</li>
})}
</ul>
</div>
</Collapse>
I use a button to display the Collapse element (from react-bootstrap), but when the Collapse gets displayed, console returns this error (I can confirm it comes exactly from the Collapse element):
findDOMNode is deprecated in StrictMode. findDOMNode was passed an instance of Transition which is inside StrictMode. Instead, add a ref directly to the element you want to reference. Learn more about using refs safely here: https://reactjs.org/link/strict-mode-find-node
Edit: I put my functional code over here in codesandbox.
how could we do to avoid this warning? Thank you for reading:)

Twinkling images in a component

I have component with navigation, on click item to child component passed in props some params, one of params - object 'itemImage' with className and url, like this:
{
url: '/static/image.svg',
className: 'absolute hidden md:block min-w-53 lg:min-w-68 mt-30 lg:mt-19 -ml-28 lg:-ml-75',
}
In child component ItemComponent:
{
itemImage &&
<img className={itemImage.className} src={itemImage.url} alt='' />
}
ItemComponent is selected from an array according to the order of the element in navigation (it is responsible for the object passed to the child component), since the list of navigation elements and elements of the array of pictures are not related and of different lengths. The sample is implemented on the basis of an index in map for objects and an index in an array with pictures, to be more precise.
Problem:
the pictures flicker as the state of the parent and the child is updated, is it possible to somehow avoid this and make the change of the picture clear without the flickering of the previous card.
You can use the below-mentioned code to render the Array of Images.
<>
{this.props.Images.map(item=>{
return (item)
})}
<p>
{JSON.stringify(this.state)}
</p>
<p>
{JSON.stringify(this.props.changed)}
</p>
<button onClick={this.props.onChange}>Change</button>
<button onClick={this.onCurrentChange}>Current State Change</button>
</>
Please check the demo here Demo
You can make somethings to try to prevent that.
1- Add a key prop to the elements. It help react understand that it is the same data from before and not re-render that piece.
2- Use react PureComponent on the flickering element https://reactjs.org/docs/react-api.html#reactpurecomponent to prevent the re-render
3 - Instead of purecomponent implement shouldComponentUpdate

Error: Unable to find element with ID 275

I am getting this error when i reload the dynamic page.
Error: Unable to find element with ID 275.
at invariant (invariant.js:38)
at precacheChildNodes (ReactDOMComponentTree.js:96)
at Object.getNodeFromInstance (ReactDOMComponentTree.js:172)
at Object.didPutListener (SimpleEventPlugin.js:210)
at Object.putListener (EventPluginHub.js:143)
at Object.putListener (ReactDOMComponent.js:176)
at CallbackQueue.notifyAll (CallbackQueue.js:76)
at ReactReconcileTransaction.close (ReactReconcileTransaction.js:80)
at ReactReconcileTransaction.closeAll (Transaction.js:206)
at ReactReconcileTransaction.perform (Transaction.js:153)
and
Uncaught (in promise) TypeError: Cannot read property 'remove' of
undefined
at Object.willDeleteListener (SimpleEventPlugin.js:220)
at Object.deleteAllListeners (EventPluginHub.js:201)
at ReactDOMComponent.unmountComponent (ReactDOMComponent.js:976)
at Object.unmountComponent (ReactReconciler.js:79)
at ReactCompositeComponentWrapper.unmountComponent (ReactCompositeComponent.js:418)
at Object.unmountComponent (ReactReconciler.js:79)
at Object.unmountChildren (ReactChildReconciler.js:146)
at ReactDOMComponent.unmountChildren (ReactMultiChild.js:373)
at ReactDOMComponent.unmountComponent (ReactDOMComponent.js:974)
at Object.unmountComponent (ReactReconciler.js:79)
In this dynamic page i have got a raw html in which i replace the part with #gallery{Id}# with component react-image-gallery. I cannot the problem because in dynamic path where i have got 2 galleries it is working well and with server side navigation and with reloading the page. But in specific dynamic path which using same dynamic component i get this error only on reload, that means if copy the link and paste it to access instantly this page i get this error. By using inspect i see
<div data-reactid="274"> // this is item in children
<p>............</p>
<div data-reactid="275"></div>//but this is another item in children that for unknow reason nested in data-reactid="274"
</div>
but i should see
<div data-reactid="274">
<p>............</p>
</div>
<div data-reactid="275"></div>
I think this happen because of more galleries to add (more data).
The thing is that when i get the array of object to render are the same when i navigating there with server side navigation and when i reload the page. I am getting the array by doing this.
children = parts.map((item, index) => {
if (typeof item === "string") {
return <div key={index} dangerouslySetInnerHTML={{ __html: item }} />
} else {
return <div key={index}>{item}</div>;
}
})
This is due to invalid HTML structure that you are setting via dangerouslySetInnerHTML. Most likely because there is tag that is not closed.
I will share my own experience with this problem to help others:
For me, the issue occurred because i was rendering children through react AND a 3rd party lib
<Mapbox>{mapLoaded ? children : null}</Mapbox>
The map code loads client side only and needs a container div reference so it can inject its <canvas> element after the page has loaded.
By moving the children outside of div reserved for the canvas, react was able to render its own children without being interrupted by nodes injected via 3rd party
<div>
<Mapbox /> {/* <- this element reserverd for canvas / element injection not handled by react */}
{mapLoaded ? children : null}
</div>
If you use a 3rd party lib that performs dom injections it is safer to always render react children outside of it.
If you are using cloudflare make sure HTML minification is disabled since it removes HTML comments that react uses to find elements.
I just burned an hour debugging this issue.
In the end, I had data-reactid attribute on my jsx left over from copying some code out of Chrome Dev tools. I thought I deleted them all, but apparently not. Interestingly, the id number being reported was not the same id hardcoded in the jsx.
react 15.6 with SSR, met this problem with unstructured HTML
<div>
{isValid
?<div>
{value1}
</div>
:{value2}
}
</div>
after warping value2 with <div>:
<div>
{isValid
?<div>
{value1}
</div>
:<div>
{value2}
</div>
}
</div>
Errors 🐛gone

React: Invariant Violation (without table)

I have looked some answer in stackoveflow. But most of them have something todo with <table> and <tbody>. But my problem is nothing to do with that.
I render this <GISMapDropdownMenu> component using ScriptjsLoader of react-google-maps library.
initialCustomSetup: function() {
let GISMapDropdownMenu = this.refs.cornermenu;
if (googleMapInstance.props.map.controls[google.maps.ControlPosition.TOP_LEFT].j.length === 0) {// push only once
googleMapInstance.props.map.controls[google.maps.ControlPosition.TOP_LEFT].push(GISMapDropdownMenu);
GISMapDropdownMenu.style.zIndex = 1;
GISMapDropdownMenu.style.display = 'inline-block';
}
},
render: function() {
return(
<ScriptjsLoader
**** some setup ****
googleMapElement={
<GoogleMap
ref={googleMap => {
if (googleMap) {
googleMapInstance = googleMap;
layerType = self.props.layerType;
self.initialCustomSetup();
}
return;
}} >
<GISMapDropdownMenu
ref="cornermenu"
availableDesa={self.props.availableDesa}
availableDesaColor={self.props.availableDesaColor} />
{self.props.children}
</GoogleMap>
}
/>);
Here is the implementation of GISMapDropdownMenu.
<div className="gmnoprint GISMap-dropdownmenu" style={{display: 'none'}}>
<div>
<div ref="icon" className="GISMap-dropdownmenu--icon" onClick={this.handleIconClick}>
<img src={BurgerIcon} draggable="false" />
</div>
<div ref="content" className="GISMap-dropdownmenu--content" style={{display: 'none'}}>
<div className="GISMap-dropdownmenu--content_header">
<div className="GISMap-dropdownmenu--content_header__title">List of Desa ({number_of_desa})</div>
<div className="GISMap-dropdownmenu--content_header__cross" onClick={this.handleCrossCLick}>
<img src={CrossIcon} draggable="false" />
</div>
</div>
<div className='GISMap-dropdownmenu--content_list'>
{array_div_element_inrange_assigned_desa}
{array_div_element_inrange_desa}
{array_div_element_assigned_desa}
</div>
</div>
</div>
</div>
{array_div_element_something} is array of this.
<div key={"desa_name-"+desa.desa_name} className={"GISMap-dropdownmenu--content_list__"+desa_color.status}>Desa {desa.desa_name}</div>;
I got this error when use <GISMapDropdownMenu /> component.
Uncaught Error: Invariant Violation: processUpdates(): Unable to find child 97 of element. This probably means the DOM was unexpectedly mutated (e.g., by the browser),
I realised something:
I move the DOM of <GISMapDropdownMenu /> component after mounted. Because I need it to be in the top left of google map.
Any suggestion?
Potential problems: First off, these are guesses as I don't do React all the time, but having said that, here are some possible causes of this:
1) Unmounting components:
This probably means that setState is being called in a callback that was firing after the component that initially started the request has already been unmounted from the dom.
More details on this type of error
2) Having incomplete HTML tags in your markup
For example, adding a <p> tag without the closing </p>. The browser likes all html tags to be complete, so if it doesn't see an end tag for something, it'll add it. Try getting the HTML of your resulting component and comparing it to what you expect. Also remove the child components bit by bit (e.g. remove ) to see when it starts to work so you know what causes this problem. Your html from what I can see doesn't cause this.
3) Build your child components before rendering
Maybe you need to do as this similar answer does
4) Changing the DOM using something other than React
Is your page using jquery or something to change this component in anyway? ie bind events or add/remove anything? If so, this can be causing that as well. Try disabling this and see if it solves the problem
If none of the above help, I'd suggest adding a JSFiddle so people can see what the problem is for sure.

Resources