Error in using react-bootstrap - reactjs

I'm using React-bootstrap package on my Keystone.JS project. To test I tried putting a button in my index page. However, I get the following warning:
Warning: Unknown props bsStyle, active, block, navItem,
navDropdown, bsClass on tag. Remove these props from the
element.
This is the code where I use Button:
var React = require('react');
var Layout = require('../../layouts/defaultLayout');
var ReactDOMServer = require('react-dom/server');
var Button = require('react-bootstrap').Button;
module.exports = React.createClass({
render: function () {
return (
<Button bsStyle="primary">Default button</Button>
);
}
});
What am I missing? Thanks for the help.

Long story short
Many component libraries (including react-bootstrap see issue) were relying on passing custom properties to DOM elements w/o data- prefix.
Starting 15.2.0 React warns about unknown properties on DOM element
Add warning for unknown properties on DOM elements. (#jimfb in #6800, #gm758 in #7152)
You need to update library. This was fixed in v0.30.0-rc.1.

Related

Replace DOM with JSX in React 18

How to remove this error message from my console
I'm using ReactDOM.render to replace certain "unreachable" parts of my code with JSX components, it worked fine in previous versions but now I'm getting this annoying error message and I want to get rid of it.
Long story:
I'm using the FullCalendar lib for react18 and Nextjs.
I'm facing a limitation from the lib, in previous versions I was able to pass JSX to render in the header buttons, but in the current version 5.11.2 it's not possible anymore, it only let you set either text or a bootstrap/font-awesome icon.
So I instead used an old known trick to replace DOM with no more than the HTML element
ReactDOM.render(
<AnyIconIWantToUse />,
window.document.querySelector("#element-to-replace-id")
)
and that is what brings up the said error message
What I've tried
As the error suggest I've tried using createRoot instead but it gives me an error too (and afaik it's meant to be used only with the root component so I prefer not to use it).
This should help you out
createPortal(
<AnyIconIWantToUse />,
document.getElementById("element-to-replace-id")
)
I ended up achieving what I wanted with another approach.
Instead of replacing DOM content directly with JSX I instead render the desired JSX into the DOM and replace the DOM with DOM
// utils/replaceDOM.ts
import type React from 'react';
import { renderToString } from 'react-dom/server';
type ReplaceDOM = (
elementToReplace: Element,
replacement: React.ReactElement
) => void;
const replaceDOM: ReplaceDOM = (elementToReplace, replacement) => {
if (!replacement) return;
// Get html from component (only get first render)
const replacementHTML = renderToString(replacement);
// Parse html string into html
const parser = new DOMParser();
const parsedDocument = parser.parseFromString(replacementHTML, 'text/html');
const replacementElement = parsedDocument.body.children[0];
// Append replacement to DOM
window.document.body.prepend(replacementElement);
// Replace children with element
elementToReplace.replaceWith(replacementElement);
};
export default replaceDOM;
Then I can use it as desired
replaceDOM(elementToReplace, <ElementIWant className="w-6" />);

React generate components with dynamic tags babel es6

I would like to be able to change the tag of a React component parent node like so
React.createClass({
render: function(){
const tagName = this.props.tagName;
const domTag = tagName ? React.DOM[tagName] : React.DOM.div;
return <domTag />
}
})
drawing reference from this question and answer
Dynamically Rendering a React component
But when I use the above method, my react component tag type is domTag...
Any ideas? I'm webpack and babel to compile the code.
The answer is ...
you just pass a string, and not the DOM function, ie.
const TagName = 'input';
return <TagName />

How to behaviour test a Component which uses React Bootstrap with Jest

In pseudo code:
MyComponent: React.createClass
doThis: () ->
//do something
render: () ->
<div>
<button className='something' onClick={clickHandler()}>click this button</button>
<ReactBootstrap.Pagination onSelect=(this.doThis) items=3 />
</div>
//tests
component = TestUtils.renderIntoDocument <MyComponent>
//test1
el = TestUtils.findRenderedDOMComponentWithClass component, 'something'
TestUtils.Simulate.click el
//test2
el = TestUtils.srcyRenderedDOMComponentsWithTag component, 'li'
TestUtils.Simulate.click el[0]
In test1 the click is fired. In test2 doThis() is not called
In both cases I definitely have a dom node and am firing the click on it. onSelect is the correct prop to use to pass to ReactBoostrap.Pagination. It works fine in the browser.
The Pagination class in Bootstrap uses onClick and seems to attach it to the li element it renders so I think I am targeting the correct element. (Edit: looking at Bootstrap-react's test for the Pagination component that targets the a tag which is rendered inside the li https://github.com/react-bootstrap/react-bootstrap/blob/master/test/PaginationSpec.js. However; I tried that too so I don't think that is my problem).
It seems to be to do with trying to target a dom node rendered by a child component. But I have no idea how to proceed. (Edit: or perhaps it is specific to react-bootstrap? Maybe I need to not mock some dependency...?)
The answer, for me, was to not mock 'classnames' - which is a dependency of react-bootstrap:
jest.dontMock 'classnames'
The answer was given by: http://racingtadpole.com/blog/test-react-with-jest/ so thanks to racingtadpole.

Using Material Design Lite with React

I am trying to use MDL on an existing project that uses React, and I am running into several issues. Things seem fine on the first load, although there are many warning messages:
Warning: ReactMount: Root element has been removed from its original container. New container:
This happens pretty much for every DOM element that has a class recognized by MDL (examples: mdl-layout, mdl-layout__content, etc.) and it happens on any DOM changes.
Further, when changing routes, there is an "Invariation Violation" error:
Uncaught Error: Invariant Violation: findComponentRoot(..., .0.2.0.1.1.0.0.0.0): Unable to find element. This probably means the DOM was unexpectedly mutated (e.g., by the browser)...
Does this mean that MDL and React are pretty much incompatible?
Update: The issue disappears if the element with class="mdl-js-layout" is not the topmost element in the reactjs render function. Once I wrapped that element, all is good.
Try to wrap a DIV element outside, I just fixed that problem in this way.
If you are using Redux + React + MDL + React-Router, You can wrap a DIV element to Provider element:
import React, { createStore } from 'react';
import { Provider } from 'react-redux';
import Router, { HistoryLocation } from 'react-router';
var store = createStore();
Router.run(routes, HistoryLocation, (Handler, state) => {
React.render((
<div>
<Provider store={store}>
{
() => <Handler {...state} />
}
</Provider>
</div>
), document.body);
});
Hope it can help you :)
The first and second errors are related to each other, take a look at MDL's layout source code. I would say that the following causes the mutation of your React root element (which is the mdl-js-layout component):
var container = document.createElement('div');
container.classList.add(this.CssClasses_.CONTAINER);
this.element_.parentElement.insertBefore(container, this.element_);
this.element_.parentElement.removeChild(this.element_);
container.appendChild(this.element_);
If you take a look at the official example, you can see that MDL massively changes your markup and that is exactly what React doesn't like.
BTW: I also have composed an article which studies the combination of React with MDL.

Output object name other than React with jsx syntax

with React v0.12 the #jsx pragma is gone which means it is no longer possible to output jsx with anything other than the React.METHODNAME syntax.
For my use case I am trying to wrap the React object in another object to provide some convenience methods thus, in my component files, I want to be able to write:
var myConvenienceObject = require('React-Wrapper');
var Component = myConvenienceObject.createSpecializedClass({
render: function () {
return <div />
}
})
However the jsx compiler automatially converts <div /> into React.createElement("div", null)
With older versions of React it was possible to handle this using the pragma at the top of the file. However, since that has been removed, I was wondering if there was any way currently to change the name of the object compiled by jsx so <div /> would be transformed into myConvenienceObject.createElement("div", null)
No, it's no longer possible to use a custom prefix for JSX. If you need to do this, you'll need to modify the JSX transform code, or create a fake React.
var React = require('react'), FakeReact = Object.assign({}, React, {
createElement: function(component, props, ...children){
// ...
// eventually call the real one
return React.createElement(component, props, ...children);
}
});
module.exports = FakeReact;
And then to use it you import the fake react and call it React.
var React = require('fake-react');
// ...
render: function(){ return <div />; }
If you would like to make some elements contains in your myConvenienceObject, you could consider the children props as shown in the doc. But this may need some changes in the myConvenienceObject too, to accept the children.
By the way, i'm not sure where is this createSpecializedClass functions comes from and what it does

Resources