Comments (7)
Okey here goes...this is probably not the best code...so please hack away and adapt as needed. It isn't a super clean solution BUT it works and keeps the bloat out of your frontend and moves it over to the build process.
// gatsby-node.js
const FiIcons = require("react-icons/fi")
const HiIcons = require("react-icons/hi")
const MdIcons = require("react-icons/md")
// Function to get the Icons needed to display
const getIcon = (icon) => {
if (icon.provider === "fi") {
const Icon = FiIcons[icon.name]
const stringIcon = `${Icon}`
const startIndex = stringIcon.indexOf("GenIcon(") + 8
const endIndex = stringIcon.lastIndexOf(")(props)")
const sliced = stringIcon.slice(startIndex, endIndex)
return sliced
}
if (icon.provider === "hi") {
const Icon = HiIcons[icon.name]
const stringIcon = `${Icon}`
const startIndex = stringIcon.indexOf("GenIcon(") + 8
const endIndex = stringIcon.lastIndexOf(")(props)")
const sliced = stringIcon.slice(startIndex, endIndex)
return sliced
}
if (icon.provider === "mdi") {
const Icon = MdIcons[icon.name]
const stringIcon = `${Icon}`
const startIndex = stringIcon.indexOf("GenIcon(") + 8
const endIndex = stringIcon.lastIndexOf(")(props)")
const sliced = stringIcon.slice(startIndex, endIndex)
return sliced
}
}
// Create the schema for GraphQL
exports.createSchemaCustomization = ({ actions, schema }) => {
const { createTypes } = actions
const sanitySocialLinksTypeDefs = `
type SanitySocialLinks implements Node {
resolvedHeaderSocialLinks: [SocialLinks]
resolvedFooterSocialLinks: [SocialLinks]
}
type SocialLinks {
iconAsString: String
link: String
name: String
}
`
createTypes(sanitySocialLinksTypeDefs)
}
// Resolve the icon data at the end of the GraphQL process after the other nodes are available
exports.createResolvers = ({ createResolvers }) => {
const iconResolvers = {
SanitySocialLinks: {
resolvedHeaderSocialLinks: {
resolve: (source, args = {}) => {
const iconObject = source.headerSocialLinks.map((socialLink) => {
return {
name: socialLink.name,
link: socialLink.link,
iconAsString: getIcon(socialLink.icon),
}
})
return iconObject
},
},
resolvedFooterSocialLinks: {
resolve: (source, args = {}) => {
const iconObject = source.footerSocialLinks.map((socialLink) => {
return {
name: socialLink.name,
link: socialLink.link,
iconAsString: getIcon(socialLink.icon),
}
})
return iconObject
},
},
},
}
createResolvers(iconResolvers)
}
// iconGenerator.js
// This component is responsible for actually resolving the icons based on data passed in from GraphQL
import { GenIcon } from "react-icons"
// icon comes in as a string from GraphQL and then is parsed back into JSON.
// Example of the format coming in
// "{"tag":"svg","attr":{"viewBox":"0 0 20 20","fill":"currentColor"},"child":[{"tag":"path","attr":{"fillRule":"evenodd","d":"M14.243 5.757a6 6 0 10-.986 9.284 1 1 0 111.087 1.678A8 8 0 1118 10a3 3 0 01-4.8 2.401A4 4 0 1114 10a1 1 0 102 0c0-1.537-.586-3.07-1.757-4.243zM12 10a2 2 0 10-4 0 2 2 0 004 0z","clipRule":"evenodd"}}]}"
const IconGenerator = ({ icon }) => {
// Parse the string back to JSON
const parsed = JSON.parse(icon)
// Pass the object into the icon generator
const Icon = GenIcon(parsed)
return <Icon />
}
export default IconGenerator
// headerSocialLinks.js
// This just takes the data that is passed to it and loops over the data to present the icons
// The query would look something like this:
// allSanitySocialLinks(
// limit: 1
// sort: { fields: _updatedAt, order: DESC }
// ) {
// nodes {
// resolvedFooterSocialLinks {
// name
// link
// iconAsString
// }
// resolvedHeaderSocialLinks {
// name
// link
// iconAsString
// }
// }
// }
import { Fragment } from "react"
import IconGenerator from "../../shared/iconGenerator"
const HeaderSocialLinks = ({ socialLinks }) => {
return (
<Fragment>
{socialLinks.map((link) => (
<li key={link.name}>
<a
href={link.link}
sx={{
py: 2,
pl: 2,
pr: 2,
":last-of-type": {
pr: 0,
},
}}
>
<IconGenerator icon={link.iconAsString} />
</a>
</li>
))}
</Fragment>
)
}
export default HeaderSocialLinks
from sanity-plugin-icon-picker.
I ended up implementing something similar to what @ehowey shared using a nextJS edge API route and reduced my bundle size with ~2MB. But it still feels like a very ugly way of doing it—it would have been so much more convenient to just get the icon as a string from the groq query directly.
from sanity-plugin-icon-picker.
I would second this as an interesting improvement to the Readme.
I hacked away at this with a Gatsby site and am pretty happy with my final solution, sure it could maybe be better though...in the case of Gatsby you do not want to use the recommended example from the issue referenced above or it will really affect your performance score because of how it affects code splitting.
Here is what I did...if you need the code just shoot me a message.
- Implement example from above inside of
gatsby-node.js
and create a custom node in the GraphQL layer called something likeresolvedIcons
. You will need to convert what you get from react-icons to a string to pass it through the GraphQL data layer. - Convert that string back to JSON on the frontend
- Use the
GenIcons
function from react-icons to generate the icons on the frontend from the JSON.
This is a bit messy BUT it prevents you from really bloating your bundle size with unneeded icons.
from sanity-plugin-icon-picker.
Thank you @ehowey for sharing. Would you mind sharing an example snippet? I think this could be really useful.
from sanity-plugin-icon-picker.
Thank you so much @ehowey will look at implementing this into readme asap
from sanity-plugin-icon-picker.
I would maybe leave it here or link it? I don't know if it is read me quality code?
from sanity-plugin-icon-picker.
@ehowey If you leave it here I'll have a look and and tweak it to a bare minimum adapted for the readme :)
from sanity-plugin-icon-picker.
Related Issues (20)
- Optimize icon provider structure HOT 1
- only provide a subset of icons by providing an array icon names
- Could you add Heroicons support? HOT 2
- Use react-icons as a source HOT 3
- Add FontAwesome Brands Icons HOT 3
- Question: How to render returned values as React component? HOT 3
- Update F7 Icons lib to use SVG components HOT 1
- Consuming the icon in a React app HOT 6
- Add icon rendering tests
- Use of decamelize 5 breaks the studio in Safari HOT 1
- Icons are a bit cut of HOT 2
- DeprecationWarning: Invalid `main` field HOT 4
- Add custom provider/lib HOT 3
- Add search icon to searchbar
- Add spinner on icon load HOT 1
- Add virtualized container to improve performance HOT 1
- Optimize ”selected” state for greater performance
- Feature request: access to icons from Sanity or other React project HOT 5
- Bug: discard changes does not reset the rendered state HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from sanity-plugin-icon-picker.