Can you instantiate another `BrowserRouter` inside a `BrowserRouter` based App? - react-router-dom

Background: I am trying to use sweetalert2-react-content to let me put a react <Link> inside a Sweetalert2 footer.
Generally speaking sweetalert2-react-content is supposed to let you place react JSX into its fields, like this:
MySwal.fire({
text: "Fire fire",
footer: <div>Call the firebrigade</div>
});
... and indeed that sort of thing does work.
However, putting a <Link> there does not work: it renders empty.
In this issue resolution message the the advice is "wrap your element in BrowserRouter like this:
MySwal.fire({
html: (
<BrowserRouter>
...
</BrowserRouter>
),
})
Is this "legitimate"? What does it "mean" to have a BrowserRouter inside an app that is routed using BrowserRouter already?

No, it is an invariant violation to nest a router within another router. I think your situation is not a case of invalid nesting, but more to do with where sweetalert is rendering the React JSX. From what I recall of sweetalert it renders content outside the ReactTree.
You can certainly render more than one router, so long as they are not nested, but then the issue is that you've separate routing contexts that each individually handle routing/navigation, and navigating within one routing context doesn't update the others.
I suspect you could use a single custom history reference and pass these to the routers you need, so they all reference the same history context internally.
react-router-dom#6 exports a HistoryRouter for this purpose.
Example:
import { createBrowserHistory } from "history";
const history = createBrowserHistory({ window });
export default history;
...
import * as React from "react";
import * as ReactDOM from "react-dom";
import { unstable_HistoryRouter as HistoryRouter } from "react-router-dom";
import history from "../path/to/history";
ReactDOM.render(
<HistoryRouter history={history}>
{/* The rest of your app goes here */}
</HistoryRouter>,
root
);
...
import { unstable_HistoryRouter as HistoryRouter } from "react-router-dom";
import history from "../path/to/history";
MySwal.fire({
html: (
<HistoryRouter history={history}>
...
</HistoryRouter>
),
})
Note about unstable_HistoryRouter:
This API is currently prefixed as unstable_ because you may
unintentionally add two versions of the history library to your app,
the one you have added to your package.json and whatever version React
Router uses internally. If it is allowed by your tooling, it's
recommended to not add history as a direct dependency and instead rely
on the nested dependency from the react-router package. Once we have a
mechanism to detect mis-matched versions, this API will remove its
unstable_ prefix.

No, this is wrong and will usually throw an error.
What you would like to do is to render it like this:
<UNSAFE_LocationContext.Provider value={null as any}>
<BrowserRouter>
...
</BrowserRouter>
</UNSAFE_LocationContext.Provider>

Related

Cant import CSS from MDCTextField to style MDCTextField child elements in LitElement based WebComponent

How do you import CSS into a ES6 module?
I receive the following error in browser console;
Failed to load module script: The server responded with a
non-JavaScript MIME type of "text/css". Strict MIME type checking is
enforced for module scripts per HTML spec.
Module below:
import { LitElement, html, css } from "lit-element";
import { MDCTextField } from "#material/textfield";
import style from "#material/textfield/dist/mdc.textfield.css";
export class MyWC extends LitElement {
static get styles() { return style; } //was using return css'...'
render() {
return html`
<label class="mdc-text-field mdc-text-field--textarea">
<textarea class="mdc-text-field__input" aria-labelledby="my-label-id" rows="8" cols="40" maxlength="140"></textarea>
...blah blah blah...
</label>
`;
}
#material/textfield & lit-element installed via npm OK. I'm using es-dev-server on linux.
ps - I want to use MDC web components but keep things as simple as possible.
Any help appreciated - Thanks.
The HTML spec currently only allows to import javascript modules. This is enforced by checking that the MIME type of the imported file is a javascript one, hence the error you're getting. The fact that in some environments (especially with bundlers/transpilers) importing other resource types is possible may give the wrong impression that it is case also in the browser.
To use this kind of import
import style from "#material/textfield/dist/mdc.textfield.css";
you would need some tool capable of transforming it into a CSSResult. A typical scenario is using bundlers like Rollup or Webpack with dedicated plugins/loaders (ie rollup-plugin-lit-css or lit-css-loader).

Why is create-react-app not importing component by default in App.js when creating a new app?

So my issue is when i do "create-react-app" in terminal it creates everything like it should but in App.js it should be importing React and { Component } from "react" by default no?
Because right now it does this:
import React from "react";
And not this:
import React, { Component } from "react";
And also it's not doing: class App extends Component { ... }But rather: function App() { ... }
So when i try to use state it just fails to compile saying 'state' is undefined because of course it is if it's not importing Component.
Why is that? I have the latest version of Node.js installed. I really don't want to redo imports everytime i run create-react-app.
I'm learning React so maybe i did something wrong with my install or something, i don't know. I'm hoping it's something i overlooked and that it's easy to solve, maybe start fresh?
There are two kinds of components, Class components and Functional components. You can use whatever approach you like, either class components that extend the React.Component or functional components that do not extend the React.Component because they are pure functions. https://reactjs.org/docs/components-and-props.html

Why cannot render HTML with ReactJS

I have seen online plenty of examples and tests using React and typescript where they issue something like this:
import * as ReactDOM from 'react-dom';
ReactDOM.render(
<h1>Hello world!!</h1>, //or any other valid html snippet
document.getElementById('root') as HTMLElement
);
However, when I try to reproduce those multiple examples in my machine, I get, first a highlight error from VS code, and then when I try to bundle I get this error:
TS2686: 'React' refers to a UMD global, but the current file is a
module. Consider adding an import instead.
If instead of putting the HTML as argument of the function I write a my SimpleComponent.render(), the bundle will be produced without errors.
What is wrong with that code snippet?
Try to add import * as React from 'react'. <h1> is React component (React.createClass('h1') after transpile JSX to JavaScript), but you have imported only ReactDOM.

How do I set up a node component package to allow importing single components?

I have a Vue.js component package with a main file that looks like this:
export { default as Button } from './components/button'
export { default as Tooltip } from './components/tooltip'
export { default as Alert } from './components/alert'
This works fine when importing from the app, like:
import { Button } from 'components'
But I realized that this imports the entire library, even though I'm only asking for Button.
What do I need to do to my components library to allow importing like below, so that it only imports the button?
import Button from 'components/button"
I build the components repo uses Webpack 2, if that’s helpful.

Chessboardjs NPM package, not showing images

I am trying to use https://www.npmjs.com/package/chessboardjs package with meteor 1.13. I wrote simple react component to render the board, but it doesn't render images for some reason. The compoent code:
import React from 'react'
import ChessBoard from 'chessboardjs'
export default class GamePage extends React.Component {
render() {
return (
<div>
<div id="chessboard" style={{"width": "400px"}}></div>
</div>
)
}
componentDidMount() {
var board = ChessBoard('chessboard');
}
}
I see that .css from that package is not being used, so maybe I have to import it as well somehow?
So the assets for chessboard.js are stored somewhere in static, right? There's a question out there about Flask which might have your answer,
Integrate chessbord.js with Flask
The idea is to modify the chessboard.js library, where it src the images for the board.
Remember to clear your cache if it's not working, as the browser will hold onto to the unedited library.

Resources