i'm trying to use SVGR to convert my svg into react components and i need to use <SvgIcon /> of Material UI and pass the converted component as a prop to it.
nothing wrong with this yet.
but,
SVGR saves these component in a folder called svgCom for example and inside of this folder there is index.js plus converted svg components.
i need to wrapp all these components inside of <SvgIcon> so i don't have to wrap this icon with <SvgIcon/> again for each use case;
so far i try to add this component in template.js of SVGR but it throw me an error when try to parse .
is this the best way of doing such thing or there is better way ?
if it is what's wrong with my template.js ?
here is my templete.js :
function template(
{ template },
opts,
{ imports, componentName, props, jsx, exports },
) {
return template.ast`
${imports}
import { SvgIcon } from "#material-ui/core";
///////////////////////////////////// error here
const ${componentName} = (${props}) => <SvgIcon component={${jsx}} />
${exports}
`
}
module.exports = template
thank you.
We had the same problem and after some research I came to the following solution:
const {
identifier,
jsxClosingElement,
jsxElement,
jsxIdentifier,
jsxOpeningElement,
jsxSpreadAttribute,
} = require('#babel/types')
const iconTemplate = ({ template }, _, { componentName, jsx, exports }) => {
const wrappedJsx = jsxElement(
jsxOpeningElement(jsxIdentifier('SvgIcon'), [jsxSpreadAttribute(identifier('props'))]),
jsxClosingElement(jsxIdentifier('SvgIcon')),
[jsx],
false
)
return template.ast`
import React from 'react'
import SvgIcon from '#material-ui/core/SvgIcon'
const ${componentName} = (props) => ${wrappedJsx}
${exports}
`
}
module.exports = iconTemplate
If you don't want {...props} on the <svg> tag, you have to disable the expandProps option
Related
I have next.js wrapper project around react ui library, which is included as npm package. Is there a way to use next/image for images optimization inside this React library?
I know that import next/image inside react project is not possible. So what is the approach to optimize images with next/image if images are inside another package?
Please, help! Thanks!
Define Your own Image component and use it everywhere in your project, it might helpful!
import React from "react";
const Image = ({ src, ...props }) => {
try {
return React.createElement(require.resolve("next/image").default, {
src: typeof src === "string" ? src : src.src,
...props
});
} catch {
console.log("Not using Next.js");
return React.createElement("img", { src, ...props });
}
};
export default Image;
Use it like this (Please take this as an example)
import Image from "../utils/image";
import bg from "../assets/bg.jpg";
const Foo = () => <Image src={bg} height="640" width="959" />;
export default Foo;
I am currently trying to parse a string that contains JSX into literal JSX,and inject it into the return of my component:
import react from "react";
import { makeStyles } from '#material-ui/core/styles';
const useStyles = makeStyles(theme => ({
heading:{
color: theme.palette.secondary.dark
},
});
const Foo = () => {
const classes = useStyles();
const jsxString = "<span>foo <span className={classes.heading}>bar</span></span>"
// convert or parse jsxString into literal JSX that can be rendered or returned
// by the component.
const jsxReact = ConvertToWhatReactUnderStands(jsxString)
return (
<>
{jsxReact}
</>
);
};
export default Foo;
I am using create-react-app, and I am not intending on ejecting.
I have tried the following:
dangerouslySetInnerHTML and this does not work, when inspecting the the element I get:
<span>foo <span className="{classes.heading}">bar</span></span>
How do I go about achieving this, making sure that my styles are applied?
Also, the inner html <span/> tag was a Material-UI <Typography/> component, I had to change it because parsing it changed the component name to : <typography/> after using the following functions from these packages:
import parse from 'html-react-parser';
import ReactHtmlParser from 'react-html-parser';
import Parser from 'html-react-parser'
and the following construct dangerouslySetInnerHTML
I understand that , I would have to transpile/transform the JSX string into javascript code with something like Babel before I execute it.
For example, when using the browser version of Babel:
var jsCode = babel.transform(jsxString);
eval(jsCode.code);
But ejecting and using Babel is not an option for me.
To be breif, my question is how would I convert a string into JSX and make sure that my style Classes are are applied? Is it possible without using babel?
I need such an editor on react https://cloverhearts.github.io/quilljs-markdown/ , as you can see in it you can put markdown characters directly into the text.
when I do this
import React, { Component } from 'react'
import './App.css'
import ReactQuill from 'react-quill'
import Quill from 'quill'
import QuillMarkdown from 'quilljs-markdown'
const App = () => {
const editor = new Quill('#editor', {
theme: 'snow'
})
new QuillMarkdown(editor)
return (
<div className='app'>
{/*<MyComponent/>*/}
<div id="editor"></div>
</div>
)
}
export default App
I get error TypeError: Cannot read property 'on' of undefined
as I understand I need jQuery for work, but I use react, I found https://www.npmjs.com/package/react-quill this quilljs for react, but I don't know how to combine it with markdown https://www.npmjs.com/package/quilljs-markdown
can anyone help?
I found the solution for this after hours of trying this out.
What you have to do is this:
Create a module for ReactQuill
Register the module.
Pass modules to react quill
Shown Below.
Step 01
const modules = {
markdownOptions: {}
};
Step 02
Quill.register('modules/markdownOptions', QuillMarkdown);
Step 03
<ReactQuill
modules={modules}
/>
It seems like you are trying to initialize the Quill instance and the markdown module before the editor is ready.
Use useEffect hook to initialize it after the div has been rendered:
import {useEffect} from 'react';
...
useEffect(() => {
const editor = new Quill('#editor', {
theme: 'snow'
});
new QuillMarkdown(editor);
});
I want to apply getElementsByClassName to a element with dynamic name assigned by CSS modules in React.js. For example, if I named a class as 'firstLink' using className={styles.firstLink} in a file named RegisterPage.js, the resulting name for the class is:
The __1Ozd bit is random. How can I apply getElementsByClassName in this situation ?
CSS modules provides key-value object which you can use in the code.
Key is class name defined by you, value is generated class name.
import React from 'react'
import style from './style.module.css'
export default function Component() {
React.useEffect(() => {
console.log(document.getElementsByClassName(style.firstLink))
}, [])
return <div className={style.firstLink} />
}
And I believe there can't be any reason to use vanilla js functions like getElementsByClassName, using state and in some cases using refs should cover all cases, example:
import React from 'react'
export default function Component() {
const ref = React.useRef()
React.useEffect(() => {
console.log(ref.current) // Will output dom element
}, [])
return <div ref={ref} />
}
After some thinking, perhaps there are old-school libraries which can accept root element only by class name.
In react, behaviors such as you wanted is termed Refs, see this.
If you are building functional component do this:
const {useRef} = React
const Component =>{
styelRef = useRef()
//refer to your anchor tag style here which should be called className
const styleFnc=()=>{
styleRef.current.className = "__1Ozd"
}
return(
<a ref={styleRef} href="...." className={`RegisterPage_firstLink${styelFnc}`}></a>
)
}
I want to use marked in reactjs as described in the reactjs docs.
<div>{marked(mystring)}</div>
I use babel so I import marked like this:
import { marked } from 'marked';
Unfortunately the import statement does not work. marked is not defined.
How do I have to import marked here, so that I can use it?
Here's one way to use marked with React:
Ensure that you've installed marked
Include marked in your project's package.json file:
// package.json
{
dependencies: {
react: "^17.0.0",
marked: "^4.0.0",
},
}
Import marked in your .jsx (or related) file:
import { marked } from "marked";
Use the dangerouslySetInnerHTML approach as shown in the example below:
import React from "react";
import { marked } from "marked";
class MarkdownExample extends React.Component {
getMarkdownText() {
var rawMarkup = marked.parse("This is _Markdown_.");
return { __html: rawMarkup };
}
render() {
return <div dangerouslySetInnerHTML={this.getMarkdownText()} />;
}
}
The dangerouslySetInnerHTML attribute gives you the ability to work with raw (HTML) markup. Make sure to take care when using this attribute, though!
Alternative (Safe)
If you don't want to use dangerouslySetInnerHTML and safely render HTML. Try marked-react, which internally uses marked to render the html elements as react components
npm i marked-react
import Markdown from "marked-react";
const MarkdownComponent = () => {
return <Markdown>{rawmarkdown}</Markdown>;
};
Another alternative is react-markdown
Here is another way of using marked with React Hooks:
Create your MarkedConverter component
import { useState } from 'react'
import marked from 'marked'
export const MarkedConverter = () => {
const [markedVal, setMarkedVal] = useState(
'# Welcome to my React Markdown Previewer!'
)
return <div dangerouslySetInnerHTML={createMarkUp(markedVal)}></div>
}
Create Markup function and pass the value from MarkedConverter Component
export const createMarkUp = (val) => {
return { __html: marked(val) }
}
Finally you can import MarkedConverter Component to any of your Component
With the marked-wrapper react-marked-markdown:
import { MarkdownPreview } from 'react-marked-markdown'
export default ({ post }) => (
<div>
<h1>{ post.title }</h1>
<MarkdownPreview value={ post.content }/>
</div>
)
If you just want to import marked:
import marked from 'marked';
Then call the function in your component:
marked('# Markdown');
Here's an example on how to use marked with react:
Install marked with NPM : npm i marked
import it in your react app (this example is created with create-react-app), and using it
example of a react component using "marked"
result in the browser :
preview