React multiple imports of same file - reactjs

I know the doubt is very basic but I haven't found an answer yet.
Here it goes:
Let's say I have a utils file that exports some function and I'm using that same utils function in many of my React components.
This is what I'm currently doing:
component1:
import { parseData } from '#/utils/parser';
component2:
import { parseData } from '#/utils/parser';
How can I avoid importing it on every file?

If you are using webpack there is a plugin called PluginProvider:
And maybe you can use it like this:
new webpack.ProvidePlugin({
parseData: path.resolve(path.join(__dirname, '#/utils/parser'),
});

Related

Custom routes with defineRoutes

Does someone have some extra info about defineRoutes function in remix.config?
I have a this route:
{
"id": "routes/__main/city/$city", "path": "/city/:city",
"file":"routes/__main/city/$city.tsx"
}
and in defineRoutes I made something like this:
routes: async (defineRoutes) => {
return defineRoutes((route) => {
route("/citta/:city", "routes/__main/city/$city.tsx");
});
},
I want that both /citta/test and /city/test will go on the same file located here routes/__main/city/$city.tsx.
But when I run the code only the /citta/test route is active the other one /city/test will throw error.
As I read from the docs here https://remix.run/docs/en/v1/api/conventions#routes, what I want to achive should be possible.
Have I misunderstood the use of defineRoutes?
This can be solved without the use of defineRoutes. Revert your remix.config changes and let Remix handle the routing for you by placing your routes within app/routes.
Move routes/__main/city/$city.tsx in your app directory and add an additional folder structure app/routes/__main/citta/$city.tsx. So you have two folders /city and /citta next to each other. They will share all the nested routing that you introduced with __main.
Export the following from your app/routes/__main/citta/$city.tsx file:
import CityComponent from '~/routes/__main/city/$city';
// re-export loader, action, and all other functionality
export * from '~/routes/__main/city/$city'
// re-use the default export from your other route
export default CityComponent;
This lets you reuse the code from your city/$city.tsx file in citta/$city.tsx.
Note: Make sure to name both files in citta/ and city/ $city.tsx to avoid naming discrepancies. Otherwise your re-exported loader and action won't work as the parameter name differs.
I recently tried to colocate all my code in modules and re-export the page components from app/routes like this:
import LoginPage, from "~/modules/auth/LoginPage";
export * from "~/modules/auth/LoginPage";
export default LoginPage;
but I ran into React 18 hydration issues. The working solution for me was re-exporting this way:
import LoginPage, { action, loader } from "~/modules/auth/LoginPage";
export { action, loader };
export default LoginPage;

How does React Lazy fetch components?

I recently read about React Lazy and how it "loads" the components during run time when they are required to be rendered. I assume that "loading" here means fetching the component from the server and then rendering it.
So my question is, how does React manage this fetching of components? How does it know the exact path from where to fetch this component (given that our code will mention the relative path but fetching will require complete server path)? Does it depend on Webpack for this?
Let's look into the React code. React.lazy is defined as follows.
export function lazy<T, R>(ctor: () => Thenable<T, R>): LazyComponent<T> {
let lazyType = {
$$typeof: REACT_LAZY_TYPE,
_ctor: ctor,
// React uses these fields to store the result.
_status: -1,
_result: null,
};
if (__DEV__) {
// ... additional code only in development mode
}
return lazyType;
}
As you can see, React.lazy requires a Promise which resolves to a module with a default export containing a React component (freely cited by React Docs). This also means that not React resolves the file, but import() does. import() works as documented in the MDN.
The async import() is a new function in ES6 which is not available in all browsers but can be polyfilled by Webpack and Babel/Typescript/others.
What you often see is code like the following, which automatically splits the imported file away by Webpack.
import(/* webpackChunkName: "xyz" */ './component/XYZ')
This creates a new javascript xyz.js next to your bundle script.
If you don't use Webpack, you need to create those files by yourself. Webpack just reduces the work required from you. So you don't absolutely depend on Webpack. This approach might look like the following:
// ./component/xyz.js
export default function() { return <div>Component</div> }
// ./main.js
const OtherComponent = React.lazy(() => import('./component/xyz.js'));
export default function() { return <div>Component</div> }
And the file structure:
| public
|---| main.js
|---| component
|---| --- | main.js
As you see, no webpack required. It just makes your life easier.

Is there a way to import an MDX or MD markdown file in React and use it in a data array?

I want to make a list of blog posts and therefor I thought it would be easy to use MDX because it helps with styling each blog text. But I don't know if it's possible to import a MDX file and put it in blogs.text.
I tried to use the npm package mdx.macro with it's function importMDX, but I get an error which says that the imported file is outside the src/.
mdx.macro documentation: https://www.npmjs.com/package/mdx.macro
import React, { lazy } from 'react';
import { importMDX } from 'mdx.macro';
const blog1 = lazy(() => importMDX('./blog1.md'));
export const blogs = [
{
title: "Hello World",
subtitle: "subtitle",
text: blog1
}
];
export default blogs;
I import this file in my blog and loop through all the items. But the importMDX keeps giving me the following error:
Module not found: You attempted to import
node_modules\.cache\mdx.macro\Content.6cbf05377c.mdx.js
which falls outside of the project src/ directory.
Relative imports outside of src/ are not supported.
Maybe there's an easier option than this?
Thanks in advance!
Adding to #mfakhrusy's answer , I had to change my blogs.js file to
import { mdx } from 'mdx.macro';
import Blog1 from './Blog1.js';
export const blogs = [
{
title: "My experiences as an intern working without getting paid",
subtitle: "And the difficulties that come along with being undervalued by a company",
text: <Blog1 />
}
];
export default blogs;
And my Blog1.js file contains this
import React from 'react';
import { mdx } from 'mdx.macro';
export const Blog1 = mdx`
# Don't Panic
Since we decided a few weeks ago to adopt the leaf as legal tender, we have, of course, all become immensely rich.
`
export default Blog1;
So now I can write blogs in markdown format and loop through them to show them on my website!
According to The create-react-app imports restriction outside of src directory
It's a restriction from CRA developer. You can try to eject your CRA app and try it again. (see eject script on package json), and remove ModuleScopePlugin from webpack config. Be careful though, eject is a one-way trip, you cannot go back.
It happens because from what I've seen from the doc, the package tries to generate a cache file which being imported later by the app, and CRA would prohibit that by throwing that error you encountered.

Sonarqube : Create a custom page using react

I would like to create a custom page using react but I cannot find the documentation to do this. On the Sonarqube documentation, there only the way to create a custom page using javascript only and I don’t understand how the example plugin works with react.
Can you tell me if there is a documentation that I can use.
Short answer: There isn't. There is barely anyone (no one in fact, as far as I've seen) using custom pages currently.
However, it IS possible. You need to create a react project with Webpack (or a similar JS packager).
I also recommend using Create-React-App. This fixes a lot of the setup for you. After that, in your index.js you use the example code from the SonarQube wiki.
Here is an example:
/*
PRODUCTION ENTRYPOINT
*/
import React from 'react';
import ReactDOM from 'react-dom';
import Project from './components/Project';
import './main.css';
window.registerExtension('myplugin/coverage', function (options) {
appendCustomCSS();
let isDisplayed = true;
window.SonarRequest.getJSON('/api/measures/component', {
component: options.component.key,
metricKeys: 'coverage'
}).then(function (response) {
if (isDisplayed) {
let obj = JSON.parse(response.component.measures[0].value);
let div = document.createElement('div');
render(obj, div);
options.el.appendChild(div);
}
});
return function () {
isDisplayed = false;
};
});
function appendCustomCSS() {
let fileref = document.createElement("link");
fileref.setAttribute("rel", "stylesheet");
fileref.setAttribute("type", "text/css");
fileref.setAttribute("href", "/static/myplugin/coverage.css");
document.head.append(fileref);
}
function render(objectArray, container) {
ReactDOM.render(<div className="Coverage"><Project objects={objectArray}/></div>, container);
}

Using Browserify to create React Bundle

It's the same question as here, but I don't understand the answer. So, my question is about the answer.
The answer is
Your react.js file/module isn't exposing the variables React and
ReactDOM you instantiate. In node, you make these methods public by
modifying the module.exports object like so:
module.exports = { React: React, ReactDOM: ReactDOM }
Finally, my question is: Where do "you make these methods public"?
You are making these methods public by defining them on the module.exports property. For instance, say you have a file reactExports.js with
var iWontGetThere = 'I am in this module only';
module.exports = { React: React, ReactDOM: ReactDOM }
now in another file, you can require these methods and use them, like so:
var React = require('reactExports').React;
var SweetComponent = React.createClass({
render: function() {
return (
<div>React is cool and I can use it in here!</div>
);
}
});
module.exports = SweetComponent;
Now imagine you want to render SweetComponent in another component. If I hadn't written module.exports = SweetComponent, requiring this module in another component would have no effect as all as you would be importing an empty object {}.
Let's say I tried to console.log(React.iWontGetThere); What would happen? I would get a reference error, as it was not exported with the contents of reactExports.js-it only exists in that module, but it is not exposed.
This is a contrived example, but the interesting story here is the ability to bring in encapsulated modules. I suggest reading more about node modules here
and checking out this answer as well.
and making some examples to get the hang of it.
tl;dr: defining variables and not having a module.exports = some_value statement then requiring that same file will default to an empty object.

Resources