2

Running into an issue rendering components dynamically as the come off the CMS in the react code.

Having no problem getting & parsing the variable names into an array to be utilized in the actual rendering - but receiving errors here no matter the method I'm using:

  • Warning: is using uppercase HTML. Always use lowercase HTML tags in React.
  • Warning: is using uppercase HTML. Always use lowercase HTML tags in React.

Which clearly shows I'm using caps :)

import React, {
  Component
} from 'react';
import {
  createClient
} from 'contentful';
import CtaBlock from './CTABlock';
import DeviceList from './DeviceList';

class HomeContainer extends Component {
  constructor(props) {
    super(props);
    this.state = {
      pageCont: [],
      entries: []
    };
  }

  componentDidMount() {
    const client = createClient({
      // This is the space ID. A space is like a project folder in Contentful terms
      space: '...',
      // This is the access token for this space. Normally you get both ID and the token in the Contentful web app
      accessToken: '...'
    });

    client.getEntries({
      'sys.id': '5stYSyaM8gkiq0iOmsOyKQ'
    }).then(response => {
      this.setState({
        mainCont: response
      });
    });
  }

  getEntries = pageCont => {
    var linkedEntries = pageCont.includes.Entry;
    console.log(linkedEntries);

    return linkedEntries;
  };

  render() {
    var formattedComponents = [];
    var renderedComponents = [];

    if (this.state.mainCont) {
      //getting the type of component from the Contetful API (String)
      var componentList = this.getEntries(this.state.mainCont).map(entries => entries.sys.contentType.sys.id);

      //converting the component names to upper case 
      formattedComponents = componentList.map(comps => comps.charAt(0).toUpperCase() + comps.slice(1));

      renderedComponents = formattedComponents.map(MyComponent => {
        return <MyComponent / >
      });
    }

    return ( 
      <div>
        <h1> Dynamically Generated Components Div </h1> 
        {renderedComponents} 
      </div>
    );
  }
}

export default HomeContainer;
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>

Appreciate any insight! 

4
  • are you doing server side rendering? Commented Dec 29, 2017 at 23:49
  • Yes - which is a first for me... Commented Dec 29, 2017 at 23:51
  • what version of react? have you seen this? Commented Dec 29, 2017 at 23:59
  • 16.0.0 - I had not seen that - but don't know if that's the right resolution. My dynamic component names in JSX are actually showing as uppercase in the error message versus that one showing as camel Commented Dec 30, 2017 at 0:22

1 Answer 1

2

When I understand you right, what you want to archive is, to map a string key to a certain component, right?

So that entries.sys.contentType.sys.id contains a string like "ctaBlock"or "deviceList"?

I would suggest using a map as follows:

import CtaBlock from './CTABlock';
import DeviceList from './DeviceList';
import FallbackComponent from './FallbackComponent';
const keyMap = {
    ctaBlock : CtaBlock,
    deviceList : DeviceList,
    default: FallbackComponent,
};
...
componentList.map( entries => {
    const key = entries.sys.contentType.sys.id;
    const Component = keyMap[ key ] || keyMap.default;
    return <Component />;
} );

See an example on: https://jsfiddle.net/v7do62hL/2/

Sign up to request clarification or add additional context in comments.

2 Comments

This did work for me (with some slight tweaks). One challenge I was trying to avoid was trying to not have to do a map of all the potential component names as I'm trying to dynamically build the page from the blocks. By tying the object properties back from the CMS (contentful) - I was trying to dynamically generate without that mapping state - but just wasn't working for me unfortunately. I will go this route for now! THanks!
I think, to use a map is much more readable. It took a wile until i figured out, what you want to Archieve with your code. In order to keep the code maintainable it is important to decide for a solution that a potential new developer would easy understand. I learned over the years, that hard to read code get‘s somehow a black whole that no one wants to touch anymore. And adding new stuff to it get‘s really time consuming. That is why I think it is a good way of solving that problem.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.