How to render react-icon depending on String from Database? - reactjs

I am trying to create multiple boxes with information and every box has an Icon. Right now I have hard-coded this as following:
<Box p={10} borderRadius='lg' bg={colorMode === 'light' ? 'gray.300' : 'gray.700'}>
<Stack spacing={5}>
<Box mt={5}>
<IconContext.Provider value={{size: '10vh'}}>
<div>
<IoLogoJavascript/>
</div>
</IconContext.Provider>
</Box>
<Box><Heading>JS & TS</Heading></Box>
<Progress size="lg" value={75} hasStripe isAnimated/>
</Stack>
</Box>
Now, so that I can dynamically add more of these components, I want to implement a database.
It's easy for the most part, I just don't know how I can implement it with the react-icons components?
Should I use something else or would it be possible?

You can create a custom component but you will need to import them all.
Here an example with fa icons:
import React from "react";
import "./styles.css";
import * as Icons from "react-icons/fa";
/* Your icon name from database data can now be passed as prop */
const DynamicFaIcon = ({ name }) => {
const IconComponent = Icons[name];
if (!IconComponent) { // Return a default one
return <Icons.FaBeer />;
}
return <IconComponent />;
};
export default function App() {
return (
<div className="App">
<DynamicFaIcon name="FaAngellist" />
<DynamicFaIcon />
</div>
);
}

How do you import your icons ?
I would go the base64 way from DB to show it in frontend, cause i see no way to import them dynamically without building again React front...

Related

How to pass CSS class names in React JS

I want to change the width of a component whenever I click a button from another component
This is the button in BiCarret:
import { useState } from "react";
import { BiCaretLeft } from "react-icons/bi";
const SideBar = () => {
const [open, setOpen] = useState(true);
return (
<div className="relative">
<BiCaretLeft
className={`${
open ? "w-72" : "w-20"
} bg-red-400 absolute cursor-pointer -right-3 top-5 border rounded-full`}
color="#fff"
size={25}
onClick={setOpen(!true)}
/>
</div>
);
};
export default SideBar;
and this is the component I want to change the width on click
import "./App.css";
import SideBar from "./components/SideBar/SideBar";
function App() {
return (
<div className="app flex">
<aside className="h-screen bg-slate-700"> // change the width here
<SideBar />
</aside>
<main className="flex-1 h-screen"></main>
</div>
);
}
export default App;
You have two simple solutions, either:
Create context
Crete context and store Open value in it, change it on click and in App react to it.
Dom manipulation
In app add ID to element you would like to change and onClick in the other component use document.getElementById(THE_ID).classList.add("new-class-for-increased-width") which gets the DOM element and adds class to it.

semantic-ui-react : modify component itself without overload with new method at onClick event

I've set an example here : https://codesandbox.io/s/lucid-morning-bd8nn0
I've trying using "this." but I can't found method to do this.
I don't want to extend Label component and implement a homemaid method to do this.
I'm expecting to found a solution using native REACT / semantic-ui method to do this.
Below my code and I'd like to update Label component itself at onClick event.
import "./styles.css";
import { Label } from "semantic-ui-react";
export default function App() {
return (
<div className="App">
<Label
as="a"
color="green"
tag
onClick={(e) => {
// I'd like to update the text of this LABEL
// any idea to do this ?
}}
>
Click here to change text
</Label>
</div>
);
}
Any idea ?
Thanks for your help.
You can use local state to accomplish that:
import "./styles.css";
import { Label } from "semantic-ui-react";
import { useState } from "react";
export default function App() {
const [labelText, setLabelText] = useState("Click here to change text");
return (
<div className="App">
<Label
value="XXXXX"
as="a"
color="green"
tag
onClick={(e) => {
setLabelText("updated text");
}}
>
{labelText}
</Label>
</div>
);
}

Correct use of ReactToPrint?

The problem is that the button that is supposed to give the option to print is not working anymore.
the error in the console says:
To print a functional component ensure it is wrapped with `React.forwardRef`, and ensure the forwarded ref is used. See the README for an example: https://github.com/gregnb/react-to-print#examples
I Have already seen some solutions specifically talking about the same problem but I have not been able to make it work.
any suggestion?
this is the library i'm using: ReactToPrint npm
React To print
import { useRef } from "react";
import { useReactToPrint } from "react-to-print";
import Resume from "./Pdf/Pdf";
const Example = () => {
const componentRef = useRef();
const handlePrint = useReactToPrint({
content: () => componentRef.current
});
return (
<div >
<button onClick={handlePrint}> ------> NOT WORKING!
Descargar Pdf
</button>
<Resume ref={componentRef} /> ------> COMPONENT TO PRINT
</div>
);
};
export default Example;
Component to be printed
import React from "react";
import styled from 'styled-components';
import PdfSection from './PdfSection';
import AlienLevel from './AlienLevel';
import {connect } from 'react-redux';
class Resume extends React.Component {
renderList = () => {
return this.props.posts.diagnose.map((post) => {
return (
<PdfSection
key={post.id}
id={post.id}
divider={"/images/pdf/divider.png"}
img={"/images/alienRandom.png"}
title={post.title}
// data={post.data}
text={post.text0}
subtext={post.subtext0}
/>
);
});
};
render(){
return (
<div>
<Container>
<Page>
<Portada>
<img id="portada" src="/images/pdf/PortadaPdf.png" />
</Portada>
</Page>
<Page>
<AlienLevel
result= "{props.diagn}{"
character={"/images/pdf/alienMedio.png"}
fileName={"responseBody[4].data"}
level={"/images/pdf/level6.png"}
correct={"/images/pdf/correct.png"}
medium={"/images/pdf/medium.png"}
incorrect={"/images/pdf/incorrect.png"}
text='"Necesitas mejorar tus prácticas intergalácticas de CV, pero ya eres nivel medio!"'
/>
<div>{this.renderList()}</div>
</Page>
</Container>
</div>
);
};
}
const mapStateToProps = (state) => {
return { posts: state.posts };
};
export default connect(mapStateToProps)( Resume);
thanks in advance!
The problem is with connect() function of react-redux.
You wrapped your component in connect and connect by default does not forward ref. Which means, the ref you are passing here <Resume ref={componentRef} /> does not reach to your component.
You need to pass options { forwardRef: true } in fourth parameter of connect function connect(mapStateToProps?, mapDispatchToProps?, mergeProps?, options?).
Just change this code export default connect(mapStateToProps)(Resume); in Resume component to this
export default connect(mapStateToProps, null, null, { forwardRef: true })(Resume);
For anyone that is struggling with the same error, it seems that they found the proper way to resolve this, I actually resolved it by following the Codesandbox I found in the Github issues here si the link. hope is useful! -->
LINK TO GITHUB SPECIFIC ISSUE (SOLVED!!)
I had the same issue and I am happy to share my findings as soon as now.
The component has to be rendered somewhere using ref.
I added it to my page as hidden using React Material UI's Backdrop. Or u can hide it using hooks like examples below.
Using backdrop and only calling it when I need to preview the print. 👇👇
<Backdrop sx={{ color: "#fff", zIndex: (theme) => theme.zIndex.drawer + 1 }}
open={openBD}>
<ComponentToPrint ref={componentRef} />
</Backdrop>
Using Hooks plus display styling to only display it when needed. 👇👇
const [isReady, setIsReady] = useState("none");
<Paper style={{ display: isReady }} >
<ComponentToPrint ref={componentRef} />
</Paper>
<Button
variant="contained"
endIcon={<BackupTableRoundedIcon />}
onClick={() => setIsReady("")}
>
Start Printing
</Button>
Note: I used MUI components, if u decide to copy paste, then change Button to html <button and paper to <div. Hope this helps.

Unable to create custom tailwind component library

I try to create my own react component library based on tailwind CSS.
I start with a simple button component
import * as React from 'react'
interface Props {
text: string
onClick?(): any
}
export const Button = ({ text, onClick }: Props) => {
return (
<button onClick={onClick} className='bg-primary-500 rounded-md'>
{text}
</button>
)
}
I push it on npm : https://www.npmjs.com/package/tailwind-lib-quentin
Then I create a simple React app that use this package
import "tailwind-lib-quentin/dist/index.css";
import { Button } from "tailwind-lib-quentin";
function App() {
return (
<div className="App">
<Button text="Test" onClick={() => console.log("ok")} />
<div className="w-full h-40 bg-primary-500">Bonjour</div>
</div>
);
}
export default App;
as you can see I import the css of my package that extend tailwind but my components are not styled at all.
The button work but I can't see any style on it and I don't get any errors.
Here is reproductible example on Codesandbox : https://codesandbox.io/s/frosty-sea-1y879
here is the package repository : https://github.com/quentin-bardenet/tailwind-lib-quentin

Material-ui svg-icons inside another element doesnt align to the center

I'm using the material ui library in my react project, and I have come across a strange issue, when I try to use svg icons inside a button-icon, the icom doesn't align to the center.
for example:
<ListItem key={product.id}
primaryText={product.title}
leftAvatar={<Avatar src={product.img}/>}
rightIcon={<IconButton><RemoveIcon/></IconButton>}/>
for this code I will get the following result:
And for this code:
<ListItem key={product.id}
primaryText={product.title}
leftAvatar={<Avatar src={product.img}/>}
rightIcon={<RemoveIcon/>}/>
I will get the following result :
My question is, how do i get to the result of my second example, but that the icon will we inside another element?
This is kind of late but I recently had the same issue and solved it by wrapping the IconButton component in a custom component and extending the css. You may have to change some other CSS to make it align perfectly but this worked for my use case.
import React, { PropTypes, Component } from 'react';
import IconButton from 'material-ui/IconButton';
const CustomIconButton = (props) => {
const { style } = props;
const additionalStyles = {
marginTop: '0'
};
return(
<IconButton {...props } style={{ ...style, ...additionalStyles }} iconStyle={{ fontSize: '20px' }}/>
);
};
CustomIconButton.PropTypes = {
// listed all the props that IconButton requires (check docs)
};
export default PPIconButton;
This is what a simplified usage of this custom IconButton looks like:
const deleteIconButton = (deleteFunc) => {
return <CustomIconButton
touch={true}
tooltip="Delete"
tooltipPosition="top-right"
onTouchTap={deleteFeed}
iconClassName="fa fa-trash"
/>;
};
class MyList extends Component {
render() {
return (
<div>
<List>
<ListItem value={ i } primaryText="My List Item" rightIcon={ deleteIconButton(() => this.props.deleteFeed(i) } />
) }
</List>
</div>
);
}
}
Passing the styles down to the inner element worked for me:
return <SvgIcon style={this.props.style} />
check this code, working fine for me
import React from 'react';
import List from 'material-ui/List';
import ListItem from 'material-ui/List/ListItem';
import Delete from 'material-ui/svg-icons/action/delete';
const MenuExampleIcons = () => (
<div>
<List style={{width:"300px"}}>
<ListItem primaryText="New Config" leftIcon={<Delete />} />
<ListItem primaryText="New Config" rightIcon={<Delete />} />
</List>
</div>
);
export default MenuExampleIcons;

Resources