skip to Main Content

I have a few react components (for eg:like below)

import AloneTab from './tab/AloneTab'
import BiTab from './tab/BiTab'
import CalTab from './tab/CalTab'
import DelTab from './tab/DelTab'

I have an array obj={"Alone":true,"Bi":true,"Cal":false,"Del":true}

Currently, I am rendering the components inside a div like so (just a representation)

<div>
 {obj["Alone"]? <AloneTab/>: null}
 {obj["Bi"]? <BiTab/>: null}
 {obj["Cal"]? <CalTab/>: null}
 {obj["Del"]? <delTab/>: null}
</div>

3 components will render ( will not render since "Cal":false)

I have just shown only a few components but there are many more & repeating the code again & again is not nice. Is there a way to loop over the items & renders the components?

I tired

const keys=  Object.keys(obj)
const values=  Object.values(obj)

const tabs = keys.map((tab, index)=>
        values[index] ? <`${tab}Tab`/> :null)

<div>
 {tabs}
</div>

However, this does not work. Is there anyway to make this work?

2

Answers


  1. Is there anyway to make this work?

    Nope, unless you import all those components from a single file, you can’t render it from a string.

    The only option is to define a mapping from key to React component, then you can get the Component based on the name

    Example:

    const Foo = () => <em>FOO</em>;
    const Bar = () => <em>BAR</em>;
    
    const Example = () => {
    
        const data = {
            Foo: true,
            Bar: false
        }
        
        const mapping = {
            Foo: Foo,
            Bar: Bar
        }
    
        return (
            <div>
                {
                    (Object.keys(data)).map(k => {
                        if (!data[k]) return null;
                        const Component = mapping[k];
                        return <Component />
                    })
                }
            </div>
        )
    }
    ReactDOM.render(<Example />, document.getElementById("react"));
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script>
    <div id="react"></div>

    If you could change your import to get all those Tab’s from a single file:

    import AllTabComponents from './tabs/allTabs.jsx;
    

    You could use that as the mapping:

    return <AllTabComponents["Alone"] />
    
    Login or Signup to reply.
  2. One method of making this work is to store the component within the object and associate it with the relevant key. Store this along with the boolean value of whether or not it should be shown.
    Please see below:

    // ./TabOne.js
    export default function TabOne() { return <div>Tab One</div>; }
    // Repeat for TabTwo, TabThree and TabFour
    
    // App.js
    import TabOne from "./TabOne.js";
    import TabTwo from "./TabTwo.js";
    import TabThree from "./TabThree.js";
    import TabFour from "./TabFour.js";
    
    export default function App() {
      const data = {
        "one": { "show": true, "content": <TabOne /> },
        "two": { "show": false, "content": <TabTwo /> },
        "three": { "show": true, "content": <TabThree /> },
        "four": { "show": false, "content": <TabFour /> }
      }
    
      return (
        <div className="App">
          {
            Object.keys(data).map(key => {
              return data[key].show 
                ? <div key={key}>{data[key].content}</div> 
                : null
            })}
        </div>
      );
    }
    

    The above returns:

    Tab One
    Tab Three
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search