I created a React application with npx create-react-app.
Then following these instructions
https://fontawesome.com/how-to-use/on-the-web/using-with/react
I installed the Font Awesome dependences:
npm i #fortawesome/fontawesome-svg-core
npm i #fortawesome/free-solid-svg-icons
npm i #fortawesome/react-fontawesome
Then I changed the App.js to this:
import logo from './logo.svg';
import './App.css';
import { FaSpinner } from 'react-icons/fa';
function App() {
return (
<div className="App">
<FaSpinner icon="spinner" spin /> This is a test.
</div>
);
}
export default App;
But it only displays a spinner icon that is not spinning:
How do I get the spinner to spin?
NOTE:
Outside of React, Font Awesome works fine without doing any extra work to animate the icons, e.g. this simple HTML code shows an animated icon:
<!DOCTYPE html>
<html lang="en">
<head>
<link rel="stylesheet"
type="text/css"
href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" />
<title>testspin</title>
</head>
<body>
<i class="fa fa-spinner fa-spin"
aria-hidden="true"></i>
This is a test
</body>
</html>
What do I need to do in order to get the React version to work this easily?
By default, the spinner will not spin. But a simple way to trigger it to spin just like the logo of React after creating a new react app.
Add a className of spin to the icon and add a little css to trigger it spinning such like that below:
App.js
import react from 'react';
import './App.css';
import { FaSpinner } from 'react-icons/fa';
function App() {
return (
<div className="App">
<FaSpinner icon="spinner" className="spinner" /> This is a test.
</div>
);
}
export default App;
App.css
.spinner {
animation: spin infinite 5s linear;
/*You can increase or decrease the timer (5s) to
increase or decrease the speed of the spinner*/
}
#keyframes spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
Actually you just need to add the class fa-spin, no need to add any custom css, this is already included with React-Fontawesome for the class fa-spin. Here is an example from a project of mine:
import React, { useState } from 'react'
import { faCog, faFilePdf } from '#fortawesome/free-solid-svg-icons'
import { Button } from 'react-bootstrap'
const MyComponent = () => {
const [pdfCreatingState,setPdfCreatingState] = useState(false);
const handleClick = ev => {
setPdfCreatingState(true);
setTimeout(() => generatePDFDocument(docData,docName));
}
const generatePDFDocument = async (docData,docName) => {
...
}
return(
<Button className="mr-4" onClick={handleClick}>
<FontAwesomeIcon icon={pdfCreatingState ? faCog : faFilePdf} title={"Generate PDF report"} className={pdfCreatingState ? "fa-spin" : ""} />
</Button>
);
}
I had the same situation with Nextjs and noticed that the proper <style> tag for animation was not being generated. So I solved the problem by directly importing it. In my case, Adding import "#fortawesome/fontawesome-svg-core/styles.css" fixes the issue, and FontAwesome works as intended.
In my project I'm using react-icons/fa and the answer provided by #Qudusayo worked very well for smooth spinners. If anyone is trying to create a 'pulsed' or 'step' spinner, here's how you can do that:
CSS:
.icon_pulse {
animation: circle 1.2s steps(8) infinite;
}
#keyframes circle {
from {
transform: rotate(90deg);
}
to {
transform: rotate(450deg);
}
}
JSX:
<FaSpinner className="icon_pulse" />
Related
I have some problem with icons and style were used in NextJs. I use material-ui in my project, developed time everything is ok but when i build project, the icons first be large then it gets normal. I try used other icon sets but result isn't change. Is it a NextJs bug?.
Before :
After :
This seem to help me with MUI icons
Before:
<WebAssetOffIcon sx={{maxWidth: 60, maxHeight: 60 }} />
After:
<WebAssetOffIcon style={{ maxWidth: 60, maxHeight: 60 }} />
Somone mentioned:
"The cause is the fact that the icon is being rendered before the CSS is loaded."
You can use the width property to set the icon default size, so when the CSS completely loads, they change to the icon's size.
<Icon width="16" />
add below code to your app.js/ts file it should fix your problem
import { config } from '#fortawesome/fontawesome-svg-core' // 👈
import '#fortawesome/fontawesome-svg-core/styles.css' // 👈
config.autoAddCss = false // 👈
credit goes https://github.com/FortAwesome/react-fontawesome/issues/234
Please add this code to "_document.js"
_document.js
import Document, {Html, Head, NextScript, Main} from 'next/document'
import {ServerStyleSheet} from 'styled-components';
export default class MyDocument extends Document {
static getInitialProps({renderPage}) {
const sheet = new ServerStyleSheet();
const page = renderPage(App => props => sheet.collectStyles(<App {...props}/>));
const styleTags = sheet.getStyleElement();
return {...page, styleTags};
}
render() {
return (
<Html lang="en">
<Head/>
<body>
<Main />
<NextScript/>
</body>
</Html>
)
}
}
~ Storm In Talent
This started happening suddenly when debugging a seemingly unrelated error on Netlify build. I do not have this issue locally. I've cleared my cache, deleted my package-lock and node module folder and updated everything, as well as ran a build without cache on Netlify. I've checked the file/folder names for case sensitive also. What could it be?
One of the templates the component is used:
import React, { Component } from 'react'
import GridTemplate from '../components/GridTemplate/GridTemplate.js'
import { graphql } from 'gatsby'
...
class Mediums extends Component {
render() {
let allTitles = []
this.props.data.allMarkdownRemark.edges.forEach( post => {
allTitles.push(post.node.frontmatter.title)
})
return (
<div style={{position: "absolute", width: "100%", height: "100%", overflow: "hidden", overflowY: "scroll"}}>
<HeaderMeta subTitle={this.props.pageContext.medium} itemGroup={this.props.data.allMarkdownRemark}/>
<GridTemplate
data={this.props.data.allMarkdownRemark.edges}
title={this.props.pageContext.medium}
pastUrl={this.props.location.pathname}
/>
</div>
)
}
}
export default Mediums
The GridTemplate component:
import React, { Component } from 'react';
import S from './imageGrid.module.sass'
import ArtImage from '../ArtImgae/ArtImage.js'
import Link from 'gatsby-link'
import { arrowSvg } from '../../img/svg-index.js'
import InlineSVG from 'svg-inline-react'
import Header from '../Header/Header.js'
import 'typeface-alegreya-sans-sc'
import 'typeface-cinzel-decorative'
import 'typeface-cinzel'
class GridTemplate extends Component {
render() {
const postLinks = this.props.data.map( post => {
const frontmatter = post.node.frontmatter
return (
<div key={post.node.fields.slug} className={S.imageItem}>
<Link
to={post.node.fields.slug}
//pass prop of cat / med paths for back button on art item
state={{pastUrl: this.props.pastUrl || null}}
>
<h2>{frontmatter.title}</h2>
<ArtImage
fluid={frontmatter.featuredImage.childImageSharp.fluid}
imageData={frontmatter}
/>
</Link>
</div>
)
})
//from context
const title = this.props.title
//const totalCount = this.props.data.allMarkdownRemark.totalCount not used
return (
<section id={S.GridTemplate}>
<div className={S.headerHolder}>
<Header to={["home", "archive"]} white={true} />
</div>
<div className={S.titleHolder}>
<Link to = "/store" className={S.storeLink} >
<InlineSVG src={arrowSvg} />
</Link>
<h1 id={S.mediumTitle}>{title}</h1>
</div>
<div className={S.imageGrid}>
{postLinks}
</div>
</section>
)
}
}
export default GridTemplate
File structure:
The component GridTemplate.js is used by categorys.js and mediums.js
Found it. Turns out my renaming of the path to the component folder to uppercase was never noticed by my Mac OS, despite appearing uppercase. On Githubs end, the path was still lower case, which was wrong. Used this gude to rename from Githubs end.
Try again deployment to netlify after changing import type-
from
import GridTemplate from '../components/GridTemplate/GridTemplate.js'
to
import GridTemplate from '../components/GridTemplate/GridTemplate'
I had the same issue when trying to deploy to Netlify:
can't resolve '../components/search/index' in '/opt/build/repo/src/pages'
My original line was:
import Search from "../components/search/index";
Please notice the lowercase for the directory name search. For some reason I had to rename the folder to uppercase Search, i.e.,:
import Search from "../components/Search/index";
and Netlify would build successfully.
So i'm new to React and trying to add a scroll bar to app. I've installed react-perfect-scrollbar and imported it to my app. After following instructions as specified I can't get a scroll bar to show... I imagine i'm making a very basic mistake but I can't work it out. I'm not fiddling with custom options or anything yet, i'm simply trying to display a scroll bar
import PerfectScrollbar from 'react-perfect-scrollbar';
import 'react-perfect-scrollbar/dist/css/styles.css';
<PerfectScrollbar>
<p> test 1 </p>
<p> test 2 </p>
</PerfectScrollbar>
You are not providing correct css for scrollbar to be shown.
Working codesandbox code here
Example.js
import React, { Component } from "react";
import ScrollBar from "react-perfect-scrollbar";
import "react-perfect-scrollbar/dist/css/styles.css";
import "./example.scss";
class Example extends Component {
render() {
return (
<div className="example">
<ScrollBar component="div">
<div className="content" />
</ScrollBar>
</div>
);
}
}
export default Example;
example.scss
.example {
width: 400px;
height: 400px;
.content {
background: green;
width: 800px;
height: 480px;
}
}
Hope that helps!!!
Have you tried to put your items inside DIV?
import PerfectScrollbar from 'react-perfect-scrollbar';
import 'react-perfect-scrollbar/dist/css/styles.css';
<PerfectScrollbar>
<div>
<p> test 1 </p>
<p> test 2 </p>
</div>
</PerfectScrollbar>
I'm trying to test a react component and use expect(elm).not.toBeVisible() without success.
Update 3
I have cut down the code into this simpler form:
// ./TestItem.js
import React from 'react'
import './TestItem.css'
export default ({ hide }) => {
return <div className={hide ? 'shouldHide' : ''}>Text</div>
}
// ./__tests__/TestItem.test.js
import React from 'react'
import { render } from 'react-testing-library'
import TestItem from '../TestItem'
import 'jest-dom/extend-expect'
import 'react-testing-library/cleanup-after-each'
test.only('TestItem should render correctly', async () => {
const { getByText, debug } = render(<TestItem hide={true} />)
const itemNode = getByText('Text')
debug()
expect(itemNode).not.toBeVisible()
})
// ./TestItem.css
.shouldHide {
display: none;
}
Test result:
TestItem should render correctly
expect(element).not.toBeVisible()
Received element is visible:
<div class="shouldHide" />
7 | const itemNode = getByText('Text')
8 | debug()
> 9 | expect(itemNode).not.toBeVisible()
| ^
10 | })
11 |
debug() log:
console.log node_modules/react-testing-library/dist/index.js:58
<body>
<div>
<div
class="shouldHide"
>
Text
</div>
</div>
</body>
Update 2:
Okay it's getting pretty weird because I got the test to pass on codesanbox but still find no luck on my local machine.
My original question:
I use React, semantic-ui-react and react-testing-library.
Here is the code:
// ComboItem.test.js
import React from 'react'
import ComboItem from '../ComboItem'
import { render } from 'react-testing-library'
import comboXoi from '../images/combo-xoi.jpg'
import 'path/to/semantic/semantic.min.css'
describe('ComboItem', () => {
test('should render', async () => {
const { getByText, debug } = render(
<ComboItem image={comboXoi} outOfStock={false} />
)
const outOfStockNotice = getByText('Out of stock')
debug()
expect(outOfStockNotice).not.toBeVisible()
})
})
// ComboItem.js
import React from 'react'
import { Card, Image } from 'semantic-ui-react'
export default ({ image, outOfStock = false }) => {
return (
<Card>
<Image
src={image}
dimmer={{
active: outOfStock,
inverted: true,
'data-testid': 'combo-item-dimmer',
content: (
<span style={{ marginTop: 'auto', color: 'black' }}>
Out of stock
</span>
),
}}
/>
</Card>
)
}
What i get is the result here:
ComboItem › should render
expect(element).not.toBeVisible()
Received element is visible:
<span style="margin-top: auto; color: black;" />
at Object.test (src/app/screens/App/screens/SaleEntries/screens/CreateSaleEntry/screens/StickyRiceComboSelect/__tests__/ComboItem.test.js:14:34)
at process._tickCallback (internal/process/next_tick.js:68:7)
I have tried to see the component render result on the browser and the node outOfStockNotice in the test code is actually hidden because its parent, which is a div with class dimmer has style display: none.
According to jest-dom doc (which is used by testing-react-library:
toBeVisible
An element is visible if all the following conditions are met:
it does not have its css property display set to none
it does not have its css property visibility set to either hidden or collapse
it does not have its css property opacity set to 0
its parent element is also visible (and so on up to the top of the DOM tree)
Please help. I really don't know what could go wrong here.
Update:
I include the result of debug() here:
console.log node_modules/react-testing-library/dist/index.js:58
<body>
<div>
<div
class="ui card"
>
<div
class="ui image"
>
<div
class="ui inverted dimmer"
data-testid="combo-item-dimmer"
>
<div
class="content"
>
<span
style="margin-top: auto; color: black;"
>
Out of stock
</span>
</div>
</div>
<img
src="combo-xoi.jpg"
/>
</div>
</div>
</div>
</body>
Here is the answer according to the author of react-testing-library himself:
Probably a JSDOM limitation (in codesandbox it runs in the real browser). Actually, the problem is that the css isn't actually loaded into the document in JSDOM. If it were, then that would work. If you can come up with a custom jest transform that could insert the css file into the document during tests, then you'd be set.
So this would work if you were using CSS-in-JS.
So basically the import './TestItem.css' part in the test will not works because JSDOM doesn't load it, therefore jest-dom could not understand the class shouldHide means display: none.
Update:
According to this Stack Overflow thread, you can insert css into jsdom:
import React from 'react'
import { render } from 'react-testing-library'
import TestItem from '../TestItem'
import fs from 'fs'
import path from 'path'
test.only('TestItem should render correctly', async () => {
const cssFile = fs.readFileSync(
path.resolve(__dirname, '../TestItem.css'),
'utf8'
)
const { container, getByText, debug } = render(<TestItem hide={true} />)
const style = document.createElement('style')
style.type = 'text/css'
style.innerHTML = cssFile
container.append(style)
const itemNode = getByText('Text')
debug()
expect(itemNode).not.toBeVisible()
})
And then the test should pass.
I am trying to add Slimscroll to a ReactJS app and I see the scrollbar reflect in the browser dev tools but I am getting an error in the console and the UI is breaking. AS a sidenote, the app compiles successfully.
This is my App.js
import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import { connect } from 'react-redux';
import classnames from 'classnames';
import 'jquery-slimscroll/jquery.slimscroll.min';
import injectTapEventPlugin from 'react-tap-event-plugin';
import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider';
import getMuiTheme from 'material-ui/styles/getMuiTheme';
class App extends Component {
componentDidMount() {
$(".scroll").slimscroll({
height: '100%'
});
}
render() {
<MuiThemeProvider muiTheme={getMuiTheme(materialUITheme)}>
<div id="app-inner">
....blah blah blah....
</div>
</MuiThemeProvider>
};
}
module.exports = App;
Then in the index.html I added the scroll class to the <body>
I intend to use this on other places with an overflow like scrolling tables or lists, so I'd rather have the slimscroll function attached to a utility class I can re-use (i.e. scroll)
As you can see below, the slimscroll is passing to the DOM
But the UI breaks because ReactJS doesn't like the method I used in some way.
Lots of things not working (i.e. the menu, the page displays partially, etc)
How can I add slimscroll to ReactJS. I looked at react-scrollbar in npm but it requires to wrap the element in <ScrollBar></ScrollBar> and I can't do that to the body
This might not be a direct answer to your question. But it will solve your original problem. IMO It's not a good idea to use jQuery plugins with React. But you can use react-scrollbar as your main container without no visual difference from adding scrolls to the body. Here is a small example.
import React from 'react';
import { render } from 'react-dom';
import { Scrollbars } from 'react-custom-scrollbars';
const App = () => (
<Scrollbars style={{ height: "100vh" }}>
<div style={{height:"2000px"}}/>
</Scrollbars>
);
render(<App />, document.getElementById('root'));
Also, make sure your html and body have no margins.
html, body{
margin: 0px;
}
Working Example: https://codesandbox.io/s/orLx4ZlL