Search code examples
javascriptreactjsobjectjsxsanity

How to return a variable in jsx and react into a react component


I am at the very beginning of creating an icon picker for sanity.io with react icons npm package. I am stuck on trying to map over an object and returning the right code for react to work using Object.values(ReactIcons).map... if I just console log one of the objects values like so ReactIcons.Fa500Px I get the following function

ƒ (props) {
  return Object(__WEBPACK_IMPORTED_MODULE_0__lib__["a" /* GenIcon */])({"tag":"svg","attr":{"viewBox":"0 0 448 512"},"child":[{"tag":"path","attr":{"d":"M103.3 344.3c-6.5-14.2-6.9-18.3 7.4-…

Now If I take the same code form the console.log and put it in a jsx or React component brackets like so <ReactIcons.Fa500Px /> it renders the icon just fine

However if I try to do that inside the map method with something like this I just get a bunch of elements in the dom the look like <x></x>. However the console.log(x) returns a series of the functions that are the same format as the one above that I just placed inside brackets before, which resulted in a icon being rendered.

{Object.values(ReactIcons).map(x =>{
    return (
      <>
    {console.log(x)}
    <x/>
    </>
    );
  })}

My final attempt to get this to work was to create a Icon function and pass props into it and render it as a component. Which did not work but here is that attempt.

function Icon(props){
  return(
    <>
      {props.value}
    </>
  )
}

{Object.values(ReactIcons).map(x =>{
 return (
    <>
      {console.log(x)} 
      <Icon value={x}/> 
    </>
   );
 })}

Here's the entire code base in order just to make sure maybe I am putting my Icon function in the wrong place.

import React from 'react'
import PropTypes from 'prop-types'
import FormField from 'part:@sanity/components/formfields/default'
import PatchEvent, {set, unset} from 'part:@sanity/form-builder/patch-event'
import * as ReactIcons from 'react-icons/fa'

console.log(ReactIcons);

const createPatchFrom = value => PatchEvent.from(value === '' ? unset() : set(String(value)))

function Icon(props){
  return(
    <>
      {props.value}
    </>
  )
}


class IconPickerCustom extends React.Component{

    static propTypes = {
        value: PropTypes.string,
        onChange: PropTypes.func.isRequired
    };

    render = () =>{
        const {type, value, onChange} = this.props
        return (
          <>
            <FormField label={type.title} description={type.description}>
              <input
                type="text"
                value={value === undefined ? '' : value}
                onChange={event => onChange(createPatchFrom(event.target.value))}
                ref={element => this._inputElement = element}
              />
            </FormField>
            {Object.values(ReactIcons).map(x =>{
              return (
                <>
              {console.log(x)} // has same result as console log below, except it is all the icons
              <Icon value={x}/> //neithr works
              <x /> //neither works
              </>
              );
            })}
            {console.log(ReactIcons.Fa500Px)}
            <ReactIcons.Fa500Px/>
          </>
        )
    }
}

export default IconPickerCustom;

Solution

  • I got help form the sanity slack, and this ended up solving my problem

    import React, { useState } from 'react';
    import PropTypes from 'prop-types'
    import FormField from 'part:@sanity/components/formfields/default'
    import PatchEvent, {set, unset} from 'part:@sanity/form-builder/patch-event'
    import * as ReactIcons from 'react-icons/fa'
    
    // const createPatchFrom = value => PatchEvent.from(value === '' ? unset() : set(String(value)))
    
    const Icon =({name}) =>{
      const TagName = ReactIcons[name];
      return !!TagName ? <TagName /> : <p>{name}</p>;
    }
    
    const Box = ({icon}) =>{
      return(
        <>
            {icon.map((iconsz) => {
                return(
                  <>
                  <button>
                    <Icon name={iconsz}/>
                  </button>
    
                  </>
                )
              }     
            )}
        </>
      ) 
    }
    
    class IconPickerCustom extends React.Component{
    
        constructor(props){
          super(props)
          const arr = [];
    
          Object.keys(ReactIcons).map(go => { 
            arr.push(go);
              this.state = {icon: arr};
            }
          )
          this.handleChange = this.handleChange.bind(this)
    
        }
    
        // createPatchFrom = value => PatchEvent.from(value === '' ? unset() : set(String(value)));
    
        handleChange = event => {
          const value = event;
          const arr = [];
          Object.keys(ReactIcons).map(go => 
            { 
              if(go.toLowerCase().includes(value)){
                arr.push(go);
              } 
              this.setState({
                icon: arr
              });
            }
          )
        };
    
        render = () =>{
          const {icon} = this.state
    
            return (
              <>
                <input
                  type="text"
                  onChange={event => this.handleChange(event.target.value)}
                />
                <Box icon={icon}/>
              </>
            )
        }
    }
    
    export default IconPickerCustom;