I am using a pro license of Fontawesome 5 with React and I have created a row header component for the header cell in a div table. The cell has Fontawesome generated svgs for the sort icons. I can't get the SVGs to rerender.
Here is my code:
export const row = (value, className, clickHandler) => (
<div className={`align-self-center text-center ${className ? className : ''}`} onClick={clickHandler}>
{value}
</div>
);
export const rowHeader = (value, className, sort, clickHandler) => {
let iconClass;
switch (sort) {
case 'asc':
iconClass = 'fas fa-sort-up';
break;
case 'desc':
iconClass = 'fas fa-sort-down';
break;
default:
iconClass = 'fal fa-sort';
break;
}
return row(<span>{value} {iconClass} <i className={iconClass + ' float-right'}/></span>, className + ' clickable', clickHandler);
};
I tried creating the <i .../>
as a separate component and that didn't work. The icons render correctly the first time appropriatelys and the iconClass
is being changed in my cell. However, the SVG element is not being rerendered.
How do I force the Fontawesome generated SVG icons to rerender when the parent element rerenders?
My solution was to add key={Math.random()}
to the SVG's containing element. Then, when it gets new props, it forces a refresh.
This is the solution that finally worked. I was able to find the documentation for using my pro license.
import FontAwesomeIcon from '@fortawesome/react-fontawesome';
import { faSortDown, faSortUp } from '@fortawesome/fontawesome-pro-solid';
import { faSort } from '@fortawesome/fontawesome-pro-light';
export const row = (value, className, clickHandler) => (
<div className={`align-self-center text-center ${className ? className : ''}`} onClick={clickHandler}>
{value}
</div>
);
export const rowHeader = (value, className, sort, clickHandler) => {
return row(<span>{value} {sortIcon(sort)}</span>, className + ' clickable', clickHandler);
};
export const sortIcon = (sort) => {
switch (sort) {
case 'asc':
return <FontAwesomeIcon icon={faSortDown} size='lg' className='float-right'/>;
case 'desc':
return <FontAwesomeIcon icon={faSortUp} size='lg' className='float-right'/>;
default:
return <FontAwesomeIcon icon={faSort} size='lg' className='float-right'/>;
}
};
Edit - Clarification:
The problem appeared to be that changing the CSS class names on the rendered SVG elements would not cause React to re-render them. Switching to the React Fontawesome library and updating the FontAwesomeIcon component worked.
The reason this doesn't work is because the svg&js flavor of Font Awesome uses a MutationObserver
which will replace all icon elements with svg
elements.
This means the DOM will be manipulated, which will cause trouble if you're using React to render the DOM. Your icons are not re-rendering, simply because React is no longer able to find them in the DOM because the Font Awesome library has replaced the original element with an svg
element. This can lead to other problems as well, see this question: Failed to execute 'removeChild' on 'Node' with FontAwesome in React
To fix this you can use the @fortawesome/react-fontawesome
library as you already mentioned in your own answer, or, if you're like me and don't like the verbosity (and having to use a private npm repo, ugh) of this approach, you can simply use the webfonts&css flavor and your problem will be solved without changing your code.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With