Giter VIP home page Giter VIP logo

Comments (7)

ehowey avatar ehowey commented on August 18, 2024 1

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.

Poggen avatar Poggen commented on August 18, 2024 1

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.

ehowey avatar ehowey commented on August 18, 2024

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.

  1. Implement example from above inside of gatsby-node.js and create a custom node in the GraphQL layer called something like resolvedIcons. You will need to convert what you get from react-icons to a string to pass it through the GraphQL data layer.
  2. Convert that string back to JSON on the frontend
  3. 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.

christopherafbjur avatar christopherafbjur commented on August 18, 2024

Thank you @ehowey for sharing. Would you mind sharing an example snippet? I think this could be really useful.

from sanity-plugin-icon-picker.

christopherafbjur avatar christopherafbjur commented on August 18, 2024

Thank you so much @ehowey will look at implementing this into readme asap 👍

from sanity-plugin-icon-picker.

ehowey avatar ehowey commented on August 18, 2024

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.

christopherafbjur avatar christopherafbjur commented on August 18, 2024

@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)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo 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.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.