reactstrap tooltip dynamic id - reactjs

I am developing a react application and using reactstrap.
I am using Tooltip Component of reactstrap which requires a target attribute, a value of target element's id. This id is being geneated dynamically and seems reactstrap tooltip doesn't like it.
Component looks like:
MovieCard.jsx
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { Col, Card, CardImg, CardBody, CardTitle, CardSubtitle, CardText, Button, Tooltip } from 'reactstrap';
import { LimitedTextTitle } from '../custom-styled/CustomStyledComponents';
class MovieCard extends Component {
constructor (props) {
super(props);
this.state = {
open: false
};
this.toggle = this.toggle.bind(this);
}
toggle () {
this.setState({
open: !this.state.open
})
}
render () {
const { imdbID, Title, Year, Rated, Plot, Country, Poster } = this.props.movie;
return (
<Col md="4">
<Card>
<CardImg
top
width="100%"
src={Poster}
alt="blah"
/>
</Card>
<CardBody>
<CardTitle>
<LimitedTextTitle id={imdbID}>
{`${Title} - (${Year})`}
</LimitedTextTitle>
<Tooltip placement='top' target={imdbID} isOpen={this.state.open} toggle={this.toggle}>
{Title}
</Tooltip>
</CardTitle>
<CardSubtitle>{`Rated: ${Rated} Country: ${Country}`}</CardSubtitle>
<CardText>{Plot}</CardText>
<Button>Read More</Button>
</CardBody>
</Col>
);
}
}
MovieCard.propTypes = {
movie: PropTypes.object.isRequired // eslint-disable-line
};
export default MovieCard;
Any suggestions?
react vesion 16.2.0
reactstrap 5.0.0-alpha.4

Was dealing with a similar problem.
Adding the code as an answer because i cannot add a comment above...
Hope it will help you or anyone else who will come across this question.
Description:
Use reactstrap tooltip for elements that are getting generated dynamically.
import React from 'react';
import ReactDOM from 'react-dom';
import 'bootstrap/dist/css/bootstrap.min.css';
import { Button, Tooltip } from 'reactstrap';
class App extends React.Component {
state = {};
toggle = targetName => {
if (!this.state[targetName]) {
this.setState({
...this.state,
[targetName]: {
tooltipOpen: true
}
});
} else {
this.setState({
...this.state,
[targetName]: {
tooltipOpen: !this.state[targetName].tooltipOpen
}
});
}
};
isToolTipOpen = targetName => {
return this.state[targetName] ? this.state[targetName].tooltipOpen : false;
};
render() {
return (
<div>
{[1, 2, 3, 4, 5, 6].map((x, i) => (
<div key={`div-${i}`}>
<Button color="link" id={`btn-${i}`}>
{x}
</Button>
<Tooltip
placement="right"
isOpen={this.isToolTipOpen(`btn-${i}`)}
target={`btn-${i}`}
toggle={() => this.toggle(`btn-${i}`)}>
Hello world!
</Tooltip>
</div>
))}
</div>
);
}
}
ReactDOM.render(<App />, document.getElementById('root'));
react: 16.9.0
reactstrap: 8.0.1
https://codesandbox.io/embed/angry-taussig-fup7i?fontsize=14

EUREKA I GOT IT!!! Building on Meir Keller's answer, there's no need to check if that state for the tooltip already exist. If it doesn't exist, it's false by default...
So long as state is defined, even if it's an empty state, this works.
This is using reactstrap's Popover, but it's the same concept.
import React, { Component, Fragment } from 'react';
import './App.css';
import 'bootstrap/dist/css/bootstrap.min.css'
import { Container, Row, Col, Input, Button, Popover } from 'reactstrap';
class App extends Component {
state = {};
toggle = (target) => {
// console.log(typeof target) // make sure this is a string
this.setState({
...state,
[target]: !this.state[target]
});
};
render() {
return (
<Container>
{["Hello", "Greetings"].map((name) => (
<Row>
<Fragment>
<Button id={name} type="button">{name}</Button>
<Popover placement="right"
isOpen={this.state[`${name}`]}
target={name}
toggle={() => this.toggle(`${name}`)}>
<PopoverBody>
You've got mail. Did you know?
</PopoverBody>
</Popover>
</Fragment>
</Row>
))}
</Container>
);
}
}
export default App;

Create a new component in modular or component directory and paste this code
import React, { useState } from "react";
import { Tooltip } from "reactstrap";
const TooltipItem = props => {
const { position='top', id } = props;
const [tooltipOpen, setTooltipOpen] = useState(false);
const toggle = () => setTooltipOpen(!tooltipOpen);
return (
<span>
<span id={"tooltip-" + id}>
{props.children}
</span>
<Tooltip
placement={position}
isOpen={tooltipOpen}
target={"tooltip-" + id}
toggle={toggle}
>
{props.title}
</Tooltip>
</span>
);
};
export default TooltipItem;
Now import and use this tooltip component
import TooltipItem from "../Tooltip";
<TooltipItem id={'edit' + data.id} title={'Edit Store'}>
<i className="fas fa-edit pointer" onClick={() => this.onEditClick(data)}/>
</TooltipItem>

I will Like to add an answer for it as already many people have mentioned many ways to deal with the problem.
But reactStrap works perfectly fine, mistakes most of the beginners are doing that while creating id they are using special characters like:
- _ / # and it can even be a space
Just keep the id a very simple combination of chars and numbers reactstrap will work totally fine

New component UncontrolledTooltip will solve the problem. Just use
<UncontrolledTooltip
placement="right"
target={`btn-${i}`}
>
{props.title}
</UncontrolledTooltip>

I tried a lot of solutions and was still having trouble with Reactstrap Tooltip crashing when the target element is not in the Dom.
I combined a couple other solutions that people posted and this is the only way it worked for me. Conditional rendering FTW.
const ElementWithTooltip = ({
dynamicIdentifier, // string, number, w/e
}): ReactElement => {
// Target element state.
const [isTargetReady, setIsTargetReady] = useState(false);
// Target element ref.
const tooltipRef = useRef(null);
// Hook to recognize that the target is ready.
useEffect(() => {
const targetElement = tooltipRef.current;
if (targetElement) {
setIsTargetReady(true);
}
}, [tooltipRef.current]);
// TSX.
return (
<>
<span ref={tooltipRef}>This is the target element</span>
{isTargetReady && <UncontrolledTooltip autohide={false} target={tooltipRef}>
Tooltippy text stuff
</UncontrolledTooltip>}
</>
);

The imdbID most probably is starting with digit i.e. 123abcdefghijklmno1234567890
Remember that tooltips can't work in that case when ID starts with a number i.e. the Tooltip's target cannot start with an integer.
all you need to do here is, change this:
<CardTitle>
<LimitedTextTitle id={imdbID}>
{`${Title} - (${Year})`}
</LimitedTextTitle>
<Tooltip placement='top' target={imdbID} isOpen={this.state.open} toggle={this.toggle}>
{Title}
</Tooltip>
</CardTitle>
to this:
<CardTitle>
<LimitedTextTitle id={`movie-${imdbID}`}>
{`${Title} - (${Year})`}
</LimitedTextTitle>
<Tooltip placement='top' target={`movie-${imdbID}`} isOpen={this.state.open} toggle={this.toggle}>
{Title}
</Tooltip>
</CardTitle>
You can avoid using state by simply switching to UncontrolledTooltip which handles all the toggle itself without asking you to handle that explicitly, like:
<CardTitle>
<LimitedTextTitle id={`movie-${imdbID}`}>
{`${Title} - (${Year})`}
</LimitedTextTitle>
<UncontrolledTooltip placement='top' target={`movie-${imdbID}`}>
{Title}
</UncontrolledTooltip>
</CardTitle>

Rendering dynamic content in tooltip in react js is very simple.
Use ReactTooltip.
For full understanding check below example.
Here I am adding requestId in tooltip as dynamically.
{
completedTransactions.map((item, id) => (
<tr key={id + 1}>
<td>{id + 1}</td>
<td>
<span data-tip={item.requestId} data-for="registerTip">
{item.TransactionId}
</span>
<ReactTooltip id="registerTip" place="top" />
</td>
<td>{item.groupName}</td>
<td>{item.purposeName}</td>
<td>{dateFormat(item.update, "dd-mm-yyyy hh:mm tt")}</td>
</tr>
));
}

Related

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.

Re-Rendering a component

I'm doing a simple todo list using React. What I fail to do is to remove an item once I click on the button.
However, if I click delete and then add a new item, it's working, but only if I add a new todo.
Edit:I've edited the post and added the parent componenet of AddMission.
import React,{useState}from 'react';
import { Button } from '../UI/Button/Button';
import Card from '../UI/Card/Card';
import classes from '../toDo/AddMission.module.css'
const AddMission = (props) => {
const [done,setDone]=useState(true);
const doneHandler=(m)=>{
m.isDeleted=true;
}
return (
<Card className={classes.users}>
<ul>
{props.missions.map((mission) => (
<li className={mission.isDeleted?classes.done:''} key={mission.id}>
{mission.mission1}
<div className={classes.btn2}>
<Button onClick={()=>{
doneHandler(mission)
}} className={classes.btn}>Done</Button>
</div>
</li>
)) }
</ul>
</Card>
);
};
export default AddMission;
import './App.css';
import React,{useState} from 'react';
import { Mission } from './components/toDo/Mission';
import AddMission from './components/toDo/AddMission';
function App() {
const [mission,setMission]=useState([]);
const [isEmpty,setIsEmpty]=useState(true);
const addMissionHandler = (miss) =>{
setIsEmpty(false);
setMission((prevMission)=>{
return[
...prevMission,
{mission1:miss,isDeleted:false,id:Math.random().toString()},
];
});
};
return (
<div className="">
<div className="App">
<Mission onAddMission={addMissionHandler}/>
{isEmpty?<h1 className="header-title">Start Your Day!</h1>:(<AddMission isVisible={mission.isDeleted} missions={mission}/>)}
</div>
</div>
);
}
const doneHandler=(m)=>{
m.isDeleted=true;
}
This is what is causing your issue, you are mutating an object directly instead of moving this edit up into the parent. In react we don't directly mutate objects because it causes side-effects such as the issue you are having, a component should only re-render when its props change and in your case you aren't changing missions, you are only changing a single object you passed in to your handler.
Because you haven't included the code which is passing in the missions props, I can't give you a very specific solution, but you need to pass something like an onChange prop into <AddMission /> so that you can pass your edited mission back.
You will also need to change your function to something like this...
const doneHandler = (m) =>{
props.onChange({
...m,
isDeleted: true,
});
}
And in your parent component you'll then need to edit the missions variable so when it is passed back in a proper re-render is called with the changed data.
Like others have mentioned it is because you are not changing any state, react will only re-render once state has been modified.
Perhaps you could do something like the below and create an array that logs all of the ids of the done missions?
I'm suggesting that way as it looks like you are styling the list items to look done, rather than filtering them out before mapping.
import React, { useState } from "react";
import { Button } from "../UI/Button/Button";
import Card from "../UI/Card/Card";
import classes from "../toDo/AddMission.module.css";
const AddMission = (props) => {
const [doneMissions, setDoneMissions] = useState([]);
return (
<Card className={classes.users}>
<ul>
{props.missions.map((mission) => (
<li
className={
doneMissions.includes(mission.id)
? classes.done
: ""
}
key={mission.id}
>
{mission.mission1}
<div className={classes.btn2}>
<Button
onClick={() => {
setDoneMissions((prevState) => {
return [...prevState, mission.id];
});
}}
className={classes.btn}
>
Done
</Button>
</div>
</li>
))}
</ul>
</Card>
);
};
export default AddMission;
Hope that helps a bit!
m.isDeleted = true;
m is mutated, so React has no way of knowing that the state has changed.
Pass a function as a prop from the parent component that allows you to update the missions state.
<Button
onClick={() => {
props.deleteMission(mission.id);
}}
className={classes.btn}
>
Done
</Button>;
In the parent component:
const deleteMission = (missionId) => {
setMissions(prevMissions => prevMissions.map(mission => mission.id === missionId ? {...mission, isDeleted: true} : mission))
}
<AddMission missions={mission} deleteMission={deleteMission} />

React how to update array useState on button click

I have seen a hundred videos and read about this, and it still doesn't make sense to me. I'm trying to update an array on a button click but when I log out the items array, it's one behind, meaning it's not reactive and gets added on the next paint. Also, I wrapped my Employee component inside a div only to be able to add an 'onClick' to it. Ideally, I'd like the onClick to be on the Employee component itself, but it doesn't work. Thanks.
import React, {ReactElement, useState } from "react";
import {TextContainer, Text } from "react-md";
import model from '../Models'
import Employee from './Employee/Employee'
import styles from '../home.module.scss'
export default function Home(): ReactElement {
const [items, setItems] = useState<Array<any>>([]);
const addItem = (val:any) => {
setItems([...items, val ])
console.log('items :', items)
}
return (
<div className='center'>
<TextContainer className='center'>
<Text type='headline-4' style={{color: 'white'}}>Employee List</Text>
</TextContainer>
<section className={styles.emp_list}>
{model.map((props, index) =><div key={index} onClick={() => addItem(props.name)}><Employee key={index} name={props.name} role={props.role} markets={props.markets} image={props.image}/></div>)}
</section>
</div>
)}
And my Employee component:
import React from "react";
import {MediaContainer} from "#react-md/media";
import styles from './employee.module.scss'
import { Card, CardContent, CardHeader} from "react-md";
function Employee(props: any) {
return (
<Card className={styles.emp_card}>
<CardHeader>
<div className={styles.emp_text}>
<p key={props.name}>Name: {props.name}</p>
<p key={props.role}>Title: {props.role}</p>
<p key={props.markets}>Markets: {props.markets[0]} {props.markets[1] && <span>and {props.markets[1]}</span>}</p>
</div>
</CardHeader>
<CardContent>
<MediaContainer>
<img key={props.image} src={props.image} alt="employee"/>
</MediaContainer>
</CardContent>
</Card>
)
}
export default Employee;
I don't think the documentation is clear enough on this, but if you want to setState using the previous state, then you should pass a function to useState. For example:
const addItem = (val:any) => {
setItems(prevItems => [...prevItems, val ])
}
https://reactjs.org/docs/hooks-reference.html#functional-updates

Visibility sensor is not working with counterup

I have been trying to implement react counterup along with react-visibility sensor. I wish to show the couterup only after that section is visible in the viewport. So, Using the visibility sensor to load it. But, it's not working and below is the error
"Error: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: object."
Sample code is below
import React from 'react';
import CountUp, { startAnimation } from 'react-countup';
const CounterSection= (props) => {
const VisibilitySensor = require('react-visibility-sensor');
function onChange(isVisible) {
console.log('Element is now %s', isVisible ? 'visible' : 'hidden');
}
return (
<div>
<VisibilitySensor onChange={onChange}>
<div>...content goes here...</div>
<CountUp start={0} end={9350} duration={5} />+
</VisibilitySensor>
</div>
);
};
Assistance on this much appreciated. Thanks
The error was that the contents inside any component should be within a single block. Also, visibility sensor should be imported and removed from required. I added the contents inside div and the error was off.
import CountUp, { startAnimation } from 'react-countup';
import VisibilitySensor from 'react-visibility-sensor';
const CounterSection= (props) => {
function onChange(isVisible) {
console.log('Element is now %s', isVisible ? 'visible' : 'hidden');
}
return (
<div>
<VisibilitySensor onChange={onChange}>
<div>
<div>...content goes here...</div>
<CountUp start={0} end={9350} duration={5} />+
</div>
</VisibilitySensor>
</div>
);
};
As a previous poster pointed out, you're importing the library improperly, import it with an import statement at the top of the component. Using the ES5 require is correct for Node/Express but not for React.
You don't need to manually handle the onChange, that's apparently an older way of getting the two libraries to work with each other. Check out this answer pertaining to using VisibilitySensor and CountUp. I just tested it out and it works for me.
VisibilitySensor does not support the feature to track the first time visibility out of the box. I will put here an example that I have been using.
AppearVisibility.js
import React, { useState } from "react";
import VisibilitySensor from "react-visibility-sensor";
/**
* VisibilitySensor does not implement some kind of funcionality to track first time
* visibility. This component extends VisibilitySensor compoment to provide this
* feature. Just use `hasBeenVisible` render prop instead of `isVisible`.
*
* https://github.com/joshwnj/react-visibility-sensor/issues/117#issuecomment-686365798
*/
const AppearSensor = ({
onChange,
children,
...rest
}) => {
const [hasBeenVisible, setHasBeenVisible] = useState(false);
return (
<VisibilitySensor {...rest} onChange={(isVisible) => {
if (isVisible) setHasBeenVisible(true)
if (onChange) onChange(isVisible)
}}>
{
({
isVisible,
...restRenderProps
}) => {
return children({ isVisible, ...restRenderProps, hasBeenVisible })
}
}
</VisibilitySensor>
);
};
AppearSensor.propTypes = VisibilitySensor.propTypes
AppearSensor.defaultProps = VisibilitySensor.defaultProps
export default AppearSensor;
CounterSection.js
import React from 'react';
import CountUp from 'react-countup';
const CounterSection = (props) => {
return (
<div>
<div>...content goes here...</div>
<AppearSensor>
{({ hasBeenVisible }) =>
hasBeenVisible
? <CountUp
start={0}
end={9350}
duration={5} />
: <span>9350</span>
}
</AppearSensor>
</div>
);
};
export default CounterSection;
import React, {Fragment,Component} from 'react';
import CountUp, { startAnimation } from 'react-countup';
import ReactVisibilitySensor from "react-visibility-sensor";
class Test extends Component {
render() {
return (
<Fragment>
<h1 className={'Countnumber'}>
<CountUp start={0} end={100} delay={0}>
{({ countUpRef,start }) => (
<ReactVisibilitySensor onChange={start} delayedCall={true}>
<span ref={countUpRef} />
</ReactVisibilitySensor>
)}
</CountUp>
</h1>
</Fragment>
);
}
}
export default Test;
This definitely works

How do I use a variable to return a named import in React?

I want to be able to have the value of a variable (generated by a map function) be used as a named object in curly braces. I'm kind of new to React and ES6 (been teaching myself through a pet project), so I may not be asking the question properly.
I'm utilizing an NPM package (react-icons-kit) that allows me to import font icons as React modules, that then are rendered as SVGs. I have a JSON file with objects (each object has: id, name, category, description, icon) and each object has a related icon assigned to it.
When I'm rendering an module, I have to specify the icon I want to use with curly braces. I am using a map function to process the JSON data to display each object nicely, and want to be able to dynamically create an icon using the map variable {obj.icon}.
import Icon from 'react-icons-kit';
import { font, clock0, html5 } from 'react-icons-kit/fa';
...
// Sample data
array = [...{"name":"Some Name","icon":"font"},{"name":"Some
Othername","icon":"html5"},{"name":"Another Name","icon":"clock0"}...]
...
// Should render an SVG icon when use with other code
var foo = array.map((obj) => {
console.log(obj.icon) // correctly logs font html5 clock0
return(
{obj.icon} // prints the value of the var fine (font html5 clock0)
<Icon icon={clock0}/> // manually specifying works
<Icon icon={obj.icon}/> // using a variable gives error
);
});
...
/*================
FULL CODE (SORRY)
=================*/
import React, { Component } from 'react';
import ScrollableAnchor from 'react-scrollable-anchor'
import { TabContent, TabPane, Nav, NavItem, NavLink, Row, Col } from 'reactstrap';
import { Media } from 'reactstrap';
import Icon from 'react-icons-kit';
import { font, clockO, html5 } from 'react-icons-kit/fa';
class Skills extends Component {
constructor(props) {
super(props);
this.state = {
activeTab: 'Coding',
};
this.toggle = this.toggle.bind(this);
}
toggle(tab) {
if (this.state.activeTab !== tab) {
this.setState({
activeTab: tab
});
}
}
render() {
// Skill Navigation
let SkillNav = () => {
let SkillNavItems = this.props.categories.map((category) => {
let active = (this.state.activeTab === category) ? "active" : "";
return (
<NavItem>
<NavLink
className={active}
onClick={() => { this.toggle(category); }}>
{category}
</NavLink>
</NavItem>
);
});
return (
<Nav pills vertical>
{SkillNavItems}
</Nav>
);
}
// Different tabs of Skills
var SkillTabs = () => {
var SkillTab = this.props.categories.map((category) => {
// Separate objects by the category supplied to it
var SkillTabCategory = this.props.skills.filter(function (skill) {
return skill.category === category;
});
// Display a list of objects with the same categories
var SkillTabContent = SkillTabCategory.map((skill) => {
return (
<Media list>
<Media tag="li">
<Media className="mr-5">
<Icon icon={skill.icon} />
</Media>
<Media body>
<Media heading>
{skill.name}
</Media>
{skill.description}
</Media>
</Media>
</Media>
);
});
return (
<TabPane tabId={category}>
<Row>
<Col sm="12">
<h4>{category}</h4>
{SkillTabContent}
</Col>
</Row>
</TabPane>
);
});
return (
<TabContent activeTab={this.state.activeTab}>
{SkillTab}
</TabContent>
);
}
return (
// Putting it all together
<ScrollableAnchor id='skills'>
<div className="wrapper">
<div className="container">
<Row className="vh100 align-items-center">
<Col xs="4" sm="4">
<SkillNav></SkillNav>
</Col>
<Col xs="12" sm="8">
<SkillTabs></SkillTabs>
</Col>
</Row>
</div>
</div>
</ScrollableAnchor>
);
}
}
export default Skills;
If your icons names come from your json means dynamically then you need to first import all the icons from react-icons-kit like .
import * as icons from 'react-icons-kit/fa';
Now you can uses icons to fetch the icons runtime like
const array = [{"name":"Some Othername","icon":"html5"}]
export default ({ name }) => (
<>
{array.map((item)=>{
return(
<Icon icon={icons[item.icon]} />
)
})}
</>
);
check running example here Demo
Codesandbox
Initialize the named-import inside the constructor function with this.font=font;this.html5=html5;.
Then render it with <Icon icon={this[obj.icon]} />

Resources