My component is supposed to retrieve the data for courses when the component mounts. The problem that I have is that whether I use the course Id or the course title as the key, I get the following error:
index.js:1 Warning: Each child in a list should have a unique "key" prop.
I have looked through the react docs, here on Stack Overflow, and tried different ways to get it to work. The only way I can get it to partially work is by adding an index as a parameter for map. When I use this method, I run into another problem and that is, it stops after the first iteration, even though there are 10 items. How can I fix this?
Here is my code:
CoursesPage.js
import React from 'react';
import { connect } from 'react-redux';
import * as courseActions from '../../redux/actions/courseActions';
import PropTypes from 'prop-types';
import { bindActionCreators } from 'redux';
class CoursesPage extends React.Component {
componentDidMount() {
this.props.actions.loadCourses().catch(error => {
alert("Loading courses failed" + error);
});
}
render() {
return (
<>
<h2>Courses</h2>
{this.props.courses.map((course, index) => (
<div key={course[index].title}>{course[index].title}</div>
))}
</>
);
}
}
CoursesPage.propTypes = {
courses: PropTypes.array.isRequired,
actions: PropTypes.object.isRequired
}
function mapStateToProps(state) {
return {
courses: state.courses
}
}
function mapDispatchToProps(dispatch) {
return {
actions: bindActionCreators(courseActions, dispatch)
}
}
export default connect(mapStateToProps, mapDispatchToProps)(CoursesPage);
My mock data:
const courses = [
{
id: 1,
title: "Securing React Apps with Auth0",
slug: "react-auth0-authentication-security",
authorId: 1,
category: "JavaScript"
},
{
id: 2,
title: "React: The Big Picture",
slug: "react-big-picture",
authorId: 1,
category: "JavaScript"
},
{
id: 3,
title: "Creating Reusable React Components",
slug: "react-creating-reusable-components",
authorId: 1,
category: "JavaScript"
},
{
id: 4,
title: "Building a JavaScript Development Environment",
slug: "javascript-development-environment",
authorId: 1,
category: "JavaScript"
},
{
id: 5,
title: "Building Applications with React and Redux",
slug: "react-redux-react-router-es6",
authorId: 1,
category: "JavaScript"
},
{
id: 6,
title: "Building Applications in React and Flux",
slug: "react-flux-building-applications",
authorId: 1,
category: "JavaScript"
},
{
id: 7,
title: "Clean Code: Writing Code for Humans",
slug: "writing-clean-code-humans",
authorId: 1,
category: "Software Practices"
},
{
id: 8,
title: "Architecture Applications for the Real World",
slug: "architecting-applications-dotnet",
authorId: 1,
category: "Software Architecture"
},
{
id: 9,
title: "Becoming an Outlier: Reprogramming the Developer Mind",
slug: "career-reboot-for-developer-mind",
authorId: 1,
category: "Career"
},
{
id: 10,
title: "Web Component Fundamentals",
slug: "web-components-shadow-dom",
authorId: 1,
category: "HTML5"
}
];
const authors = [
{ id: 1, name: "Cory House" },
{ id: 2, name: "Scott Allen" },
{ id: 3, name: "Dan Wahlin" }
];
const newCourse = {
id: null,
title: "",
authorId: null,
category: ""
};
module.exports = {
newCourse,
courses,
authors
};
Edit:
I am using Redux Thunk.
Here is my actionType.js file:
export const CREATE_COURSE = "CREATE_COURSE";
export const LOAD_COURSES_SUCCESS = "LOAD_COURSES_SUCCESS";
Here is my CourseActions.js file:
import * as types from './actionTypes';
import * as courseApi from "../../api/courseApi";
export function createCourse(course) {
return { type: types.CREATE_COURSE, course };
}
export function loadCourseSuccess(courses) {
return { type: types.LOAD_COURSES_SUCCESS, courses };
}
export function loadCourses() {
return function (dispatch) {
return courseApi.getCourses().then(courses => {
dispatch(loadCourseSuccess(courses));
}).catch(error => {
throw error;
})
}
}
Here is my courseReducer.js file:
import * as types from '../actions/actionTypes';
export default function courseReducer(state = [], action) {
switch (action.type) {
case types.CREATE_COURSE:
return [...state, { ...action.course }];
case types.LOAD_COURSES_SUCCESS:
return [...state, { ...action.courses }];
default:
return state;
}
}
Any help would be appreciated.
Thanks.
P.S. I know that you should use Id for key. But the way it has to be done for now is using the title of the course as the key.
With your edits, I think we can more effectively help you. For future, it would be beneficial to post an example of your code not working on https://codesandbox.io/
Also to help yourself out when you debug, isolate the react component from the use of redux. This will allow you to ensure your react component renders when given data, then focus on getting redux to provide you the data your react component has.
You can do this by first defining mockdata inside your react component, then moving that mock data to your reducer, then finally replacing the mock data with the live api call.
On to the code:
You have two issues: the first is that you want to index into the array courses but instead due to a typo, you are actually using the property accessor into the object course
key={course[index].title}
As your question states you must use the title as the key simply change the div to be:
<div key={course.title}>{course.title}</div> and your code should work as expected.
Once you have addressed that, then re-enable loading data from your API call using Redux, and you can address the issues with Redux.
Looking at your reducer, you have a clear bug, and depending on your use case, a potential bug:
case types.LOAD_COURSES_SUCCESS:
return [...state, { ...action.courses }];
action.courses is an array, and the code is creating a new array that contains all the elements of the previous array state and adding a new object, which contains the contents of a destructured array.courses array.
Which that does is effectively append a single object to your array, and the object is comprised of elements from your courses array. The item index becomes the key, and the item itself is the value.
You can visualize it here: https://codesandbox.io/s/divine-pond-nr3j8
Instead you want
return [...state, ...action.courses];
The second, potential bug, is that you are actually appending the results of the courses api. Which for subsequent calls to load courses, you will duplicate the data. That may be what you want, but I am going to assume that is not what you want.
So instead, your LOAD_COURSES_SUCCESS case should be rewritten to simply be:
return [...action.courses];
Since each course has a unique ID field, the problem could be solved by using the id as a key
render() {
return (
<>
<h2>Courses</h2>
{this.props.courses.map(course => (
<div key={course.id}>{course.title}</div>
))}
</>
);
}
The issue is here:
{this.props.courses.map((course, index) => (
<div key={course[index].title}>{course[index].title}</div>
))}
//course in itself is data
Solution:
{this.props.courses.map((course, index) => (
<div key={`${course.title}-${index}`}>{course.title}</div>
))}
Better way would always to take care unique id for key
Here's the code snippet for render method.
Give it a try.
*Update = use course title as key
render() {
const courseList = this.props.courses.map(course => (
<div key={course.title}></div>
));
return (
<>
<h2>Courses</h2>
<div>{courseList}</div>
</>
);
}
There are many ways you can pass the key when it is iterating...
var courses = this.state.courses.map(function(course, index) {
return(
<div key={index}>
<div key={course.title} id={course.title}>
<h2 key={"header"+course.title}>{course.title}</h2>
</div>
</div>
)
});
But you should try to pass a unique id rather than a string.
Related
I have an object:
import React, {Component} from 'react';
import ProgressBar from "./ProgressBar";
class Languages extends Component {
state = {
languages: [
{id: 1, value: "XXX", xp: 1.5},
{id: 2, value: "CCC", xp: 1},
{id: 3, value: "AAA", xp: 2}
]
}
render() {
let {languages} = this.state;
const levels = ['Test', 'Bad', 'Sorry']
return (
<div className="languages">
<ProgressBar
programming={languages}
className="languagesDisplay"
levels={levels}
title="Languages"
/>
</div>
);
}
}
export default Languages;
import React from 'react';
const ProgressBar = (props) => {
return (
<div className={props.className}>
<h3>{props.title}</h3>
<div className="years">
<span>Experiences</span>
props.levels.map((level) => {
<span>level</span>
})
</div>
<span>level</span> return props.levels.map((level) =>level)
how can i display the const ['Test', 'Bad', 'Sorry'] from Languages.js in a <span> in a different React file?
Edit after seeing your response above: If the issue is just that the above code isn't working, here are a couple of things to check.
Inside of ProgressBar you've got a couple of errors in your JSX. First, you need curly braces around your JavaScript interpolation and secondly, you're not returning anything in your .map() function. If you were using parentheses it would be an implicit return, but with the curly braces you need a return statement. Try this instead:
import React from 'react';
const ProgressBar = (props) => {
return ( <div className={props.className}>
<h3> {props.title} </h3>
<div className ="years">
<span> Experiences </span>
{props.levels.map((level) => {
return (<span>{level}</span>)
})
} </div>
)};
My initial answer, which still may be helpful for understanding what's going on:
It's not entirely clear what you want to do, but here are a couple of things that might be helpful.
What's happening in your code above is that the levels variable, which is an array of strings, is being passed down from the parent component Languages into the child component ProgressBar via the props object.
When ProgressBar is called inside of Languages, it's properties (or props) are set (programming, className, levels, title).
The levels={levels} part means that the prop levels on ProgressBar is being set to the variable levels (the array of strings).
Inside of ProgressBar all of those properties are accessible in the props object that's passed as an argument. That's why you're able to access that array of strings with props.levels.map() which will map the array of strings however you tell it to (in this case by printing each individual item within a <span> tag).
So, with that understanding of what's happening here, here are a couple of things you could do to access the levels variable elsewhere in another file.
If levels is a constant that you want to access in multiple places, you could move it outside of the body of your Languages component and export it to use it in other places.
That could look like:
import React, {
Component
} from 'react';
import ProgressBar from "./ProgressBar";
export const levels = ['Test', 'Bad', 'Sorry']
class Languages extends Component {
state = {
languages: [{
id: 1,
value: "XXX",
xp: 1.5
},
{
id: 2,
value: "CCC",
xp: 1
},
{
id: 3,
value: "AAA",
xp: 2
}
]
}
render() {
let {
languages
} = this.state;
return ( <
div className = "languages" >
<
ProgressBar programming = {
languages
}
className = "languagesDisplay"
levels = {
levels
}
title = "Languages" /
>
<
/div>
);
}
}
export default Languages;
By exporting it from the top level, you could import it in another file exactly as it is.
import { levels } from '/insert-first-file-location-here'
Another option is to pass the levels variable into another component as a prop. This way if levels gets changed at the top level, those changes will drill down into subsequent components.
import React, {Component} from 'react';
import ProgressBar from "./ProgressBar";
class Languages extends Component {
state = {
languages: [
{id: 1, value: "XXX", xp: 1.5},
{id: 2, value: "CCC", xp: 1},
{id: 3, value: "AAA", xp: 2}
]
}
render() {
let {languages} = this.state;
const levels = ['Test', 'Bad', 'Sorry']
return (
<>
<div className="languages">
<ProgressBar
programming={languages}
className="languagesDisplay"
levels={levels}
title="Languages"
/>
</div>
<AnotherComponentThatUsesLevels
levels={levels} />
</>
);
}
}
export default Languages;
And then
import React from 'react'
export const AnotherComponentThatUsesLevels (props) => {
return (
<>
{/* do something with levels here, maybe map them like before*/}
{props.levels.map((level) => (<span>{level}</span>)}
</>
)
}
Does that help understand what's happening in the example and give you a couple of ways you could use that variable in another location?
You need to export that certain constant from your file like that:
import React, {
Component
} from 'react';
import ProgressBar from "./ProgressBar";
export const levels = ['Test', 'Bad', 'Sorry']
class Languages extends Component {
state = {
languages: [{
id: 1,
value: "XXX",
xp: 1.5
},
{
id: 2,
value: "CCC",
xp: 1
},
{
id: 3,
value: "AAA",
xp: 2
}
]
}
render() {
let {
languages
} = this.state;
return (
<div className="languages">
<ProgressBar
programming={languages}
className="languagesDisplay"
levels={levels}
title="Languages"
/>
</div>
);
}
}
export default Languages;
After it, you need to import it in the file where you want to access it:
import {levels} from '/path/to/file';
I'm trying to use an array of dictionaries in python as arguement to a custom dash component and use it as array of objects
in python :
audioList_py = [
{
"name": "random",
"singer": 'waveGAN\'s music',
"cover":
'link_1.jpg',
"musicSrc":
'link_1.mp3',
},
{
"name": "random",
"singer": 'waveGAN\'s music',
"cover":
'link_2.jpg',
"musicSrc":
'link_2.mp3',
},
... etc
]
in Javascript:
audioList1_js = [
{
name: "random",
singer: 'waveGAN\'s music',
cover:'link_1.jpg',
musicSrc: 'link_1.mp3',
},
{
name: "random",
singer: 'waveGAN\'s music',
cover: 'link_2.jpg',
musicSrc: 'link_2.mp3',
},
... etc
]
Here is snippet of javascript code of the dash custom component:
export default class MusicComponent extends Component {
render() {
const {id, audioLists} = this.props;
return (
<div>
<h1>{id}</h1>
<ReactJkMusicPlayer audioLists={audio_list}/>,
</div>
);
}
}
MusicComponent.defaultProps = {};
MusicComponent.propTypes = {
/**
* The ID used to identify this component in Dash callbacks.
*/
audios: PropTypes.array,
id: PropTypes.string,
};
And using the generated component in python:
app = dash.Dash(__name__)
app.layout = html.Div([
music_component.MusicComponent(audios=audioList_py),
html.Div(id='output'),
... etc
])
But I got :
TypeError: The `music_component.MusicComponent` component (version 0.0.1) received an unexpected keyword argument: `audios`Allowed arguments: id
What I am doing wrong ?
Any help or advice will be appreciated, Thanks a lot.
Make sure you run npm run build after you make a change to your custom React component. With those proptypes you shouldn't get that error. If I remove the audios proptype I can reproduce that error.
Besides that you pass a value to the audios property:
music_component.MusicComponent(audios=audioList_py)
but you try to retrieve audioLists from props:
const {id, audioLists} = this.props;
Change this to:
const {id, audios} = this.props;
Demo
export default class MusicComponent extends Component {
render() {
const {id, audios} = this.props;
return (
<div>
<h1>{id}</h1>
<ReactJkMusicPlayer audioLists={audios} />
</div>
);
}
}
MusicComponent.defaultProps = {};
MusicComponent.propTypes = {
/**
* The ID used to identify this component in Dash callbacks.
*/
id: PropTypes.string,
audios: PropTypes.array,
};
Issue fixed, I should run : npm run build:backends to generate the Python, R and Julia class files for the components, but instead I was executing npm run build:js and this command just generate the JavaScript bundle (which didn't know about the new props).
And set the audios property in the component to be like so:
MusicComponent.defaultProps = {audios: audioList1};
MusicComponent.propTypes = {
id: PropTypes.string,
audios: PropTypes.arrayOf(PropTypes.objectOf(PropTypes.string)).isRequired
};
Started learning React and JS not too long ago.
I have a parent class 'App' that gets a an array of objects 'data' from data.js. App.js is sending that 'data' property down to the 'BookList' class. I am trying to map over said property in the BookList class and save elements in 'mappedBooks' but keep getting this error:
TypeError: this.props.books.map is not a function
DATA.JS:
const data = [
{
id: 1,
title: `The Pragmatic Programmer`,
author: `David Thomas, Andrew Hunt`,
img: `https://images-na.ssl-images-amazon.com/images/I/51cUVaBWZzL._SX380_BO1,204,203,200_.jpg`
},
{
id: 2,
title: `HTML and CSS: Design and Build Websites`,
author: `Jon Duckett`,
img: `https://images-na.ssl-images-amazon.com/images/I/31aX81I6vnL._SX351_BO1,204,203,200_.jpg`
},
{
id: 3,
title: `Coding All-in-one For Dummies`,
author: `Nikhil Abraham`,
img: `https://images-na.ssl-images-amazon.com/images/I/51RXaV0MGzL._SX397_BO1,204,203,200_.jpg`
},
{
id: 4,
title: `Learning React`,
author: `Alex Banks, Eve Porcello`,
img: `https://images-na.ssl-images-amazon.com/images/I/51FHuacxYjL._SX379_BO1,204,203,200_.jpg`
},
{
id: 5,
title: `Learning Web Design`,
author: `Jennifer Robbins`,
img: `https://images-na.ssl-images-amazon.com/images/I/51iVcZUGuoL._SX408_BO1,204,203,200_.jpg`
},
{
id: 6,
title: `JavaScript and JQuery: Interactive Front-End Web Development`,
author: `Jon Duckett`,
img: `https://images-na.ssl-images-amazon.com/images/I/41y31M-zcgL._SX400_BO1,204,203,200_.jpg`
},
{
id: 7,
title: `Head First JavaScript Programming`,
author: `Eric Freeman, Elisabeth Robson`,
img: `https://images-na.ssl-images-amazon.com/images/I/51qQTSKL2nL._SX430_BO1,204,203,200_.jpg`
},
{
id: 8,
title: `Learning Redux`,
author: `Daniel Bugl`,
img: `https://images-na.ssl-images-amazon.com/images/I/41gxBZ8GNpL._SX403_BO1,204,203,200_.jpg`
},
{
id: 9,
title: `Node.js 8 the Right Way`,
author: `Jim Wilson`,
img: `https://images-na.ssl-images-amazon.com/images/I/51t44mzlCaL._SX415_BO1,204,203,200_.jpg`
},
{
id: 10,
title: `PostgreSQL: Up and Running`,
author: `Regina Obe`,
img: `https://images-na.ssl-images-amazon.com/images/I/51FSjiYDfpL._SX379_BO1,204,203,200_.jpg`
},
{
id: 11,
title: `Fundamentals of Web Development`,
author: `Randy Connolly, Ricardo Hoar`,
img: `https://images-na.ssl-images-amazon.com/images/I/51xEzGTH6lL._SX402_BO1,204,203,200_.jpg`
},
{
id: 12,
title: `Web Design Playground`,
author: `Paul McFedries`,
img: `https://images-na.ssl-images-amazon.com/images/I/41-6F+RDbIL._SX258_BO1,204,203,200_.jpg`
}
]
export default data;
APP.JS
import React, {Component} from 'react'
import './App.css';
import BookList from './Components/BookList';
import Header from './Components/Header'
import Shelf from './Components/Shelf';
import data from './data'
class App extends Component {
constructor(){
super()
this.state ={
books : {data}
}
}
render(){
return (
<div className="App">
<Header/>
<BookList books={this.state.books}/>
<Shelf/>
</div>
);
}
}
export default App;
and BOOKLIST.JS:
import React, {Component} from 'react'
class BookList extends Component{
render(){
let mappedBooks = this.props.books.map(function(element){
return {element}
})
return(
<div className = 'BookList'>
<h1>list</h1>
</div>
)
}
}
export default BookList
in Data.js you've got
export default data;
and data is an array. So when you import data in App.js it's an array.
Try running this code snippet to get a better idea of what's going on here:
let data = [1,2,3,4]
console.log('when data is an array')
console.log('{data} is', {data})
data = {
'data': [1,2,3,4]
}
console.log('when data is an object with a property called data pointing to an array')
console.log('{data} is', {data})
console.log('but if you call a function and pass in data (as an object with data as a named property pointing to an array), you can use the curly braces to pull the array out of the object using destructuring')
function destructureData({data}) {
console.log(data)
}
destructureData(data)
So, when you do this:
this.state = {
books: { data }
}
it's actually an object property shorthand that's interpreted (in ES6) as this:
this.state = {
books: { data: data }
}
If you actually want this.state.books to be the array you imported from data.js then you set it directly:
this.state = {
books: data
}
Or, using that object property shorthand, and the fact that you've got data as a default export, you could change the import to this:
import books from './data'
And then do this:
this.state = {
books
}
If you'd like to read more about the destructuring syntax–where you use curly braces to pull data out of an object or an array–this article on MDN is a good read.
I'm new to React so this might be a very silly question but I just can't seem to get it.
I have a form which has a multi select (imported react-select) and when I select multiple options I want to sent it as an array of objects. Instead I'm sending it as an array of array of objects. I want help to sent it as an array of objects instead of array of array of objects.
import React from "react"
import Select from 'react-select'
class Skills extends React.Component{
state = {
skill: []
}
skillsDropdown = [
{ value: 'React', label: 'React' },
{ value: 'Vue', label: 'Vue' },
{ value: 'Angular', label: 'Angular' },
{ value: 'Java', label: 'Java' },
]
handleChangeSkills = skill => {
this.setState({
skill
})
console.log(skill);
}
handleSubmit = (event) => {
event.preventDefault();
const userSkill= {
skills: this.state.skill.map((item) => [{
skillName: item.value
}])
}
axios.post("http://localhost:8080/api", userSkill)
.then(response => {
console.log("User profile details from backend: ", response.data);
})
}
render(){
return (
<>
<h2>Skills</h2>
<label>Please include 3-5 of your top skills to help you stand out.</label>
<label>
<Select
options={this.state.skillsDropdown}
onChange={this.handleChangeSkills}
isMulti=true
value={skill}
/>
</label>
<button className="Next" onSubmit={this.handleSubmit}>Submit</button>
</>
)
}
}
export default Skills;
When i'm submitting the data I'm getting is
skills: [[{skillName: "React"}], [{skillName: "Vue"}]]
What I want is this
skills: [{skillName: "React"}, {skillName: "Vue"}]
Can anyone please help me with this.
TIA
The culprit is in your map function. Map automatically adds all its results to an array, and you're adding another array around it.
const userSkill= {
// culprit here
skills: this.state.skill.map((item) => [{
skillName: item.value
}])
}
Removing the [] will fix it.
const userSkill= {
skills: this.state.skill.map((item) => ({
skillName: item.value
}))
}
So, the following implementation works just fine to read JSON data and turn it into rendered components - until I try to add the children. Then, it spits out an error.
function:
const catalogRenderer = (config) => {
if (typeof KeysToComponentMap[config.component] !== "undefined") {
return React.createElement(
KeysToComponentMap[config.component],
{
key: config.key,
title: config.title
},
{
config.children && config.children.map(c => catalogRenderer(c))
}
);
}
}
error:
app.js:134 Uncaught Error: Module build failed (from ./node_modules/babel-loader/lib/index.js)
"...Scripts/CatalogRenderer.js: Unexpected token, expected "," (25:14)"
console:
},
24 | {
> 25 | config.children && config.children.map(c => catalogRenderer(c))
| ^
26 | }
27 | );
28 | }
I'm using react as part of an electron application, it's a long story about all the moving parts, but everything else so far has worked just fine. In the editor, if I move to the preceding { from that mysteriously disliked . on line 25, it's highlighting the period as if this should somehow close the bracket.
Is there something I'm not understanding about the syntax here? The same thing happens if I attempt to just map and render the children like so:
{
config.children.map(c => catalogRenderer(c))
}
I've tried enclosing the whole statement in brackets, curly braces, parentheses--no matter what I do, babel seems to expect a comma, but giving it a comma obviously doesn't help. Any idea what I'm doing wrong?
eta: This is the JSON object I'm attempting to render from:
const catConfig = {
catalog: [
{
component: 'pen',
title: `B.C. Palmer`,
key: `B.C.PalmerPen`,
children: `A child string`
},
{
component: 'content',
key: `B.C.PalmerWorldList`,
children: [
{
component: 'world',
title: `Rismere`,
key: `RismereWorld`
},
{
component: 'content',
key: `RismereSeries`,
children: [
{
component: 'series',
title: `The Eidolon War`,
key: `TheEidolonWarSeries`
},
{
component: 'content',
key: `TheEidolonWarBooks`,
children: [
{
component: 'book',
title: `Magic's Heart`,
key: `MagicsHeartBook`
},
{
component: 'book',
title: `Magic's Fury`,
key: `MagicsFuryBook`
},
{
component: 'book',
title: `Magic's Grace`,
key: `MagicsGraceBook`
}
]
}
]
}
]
},
{
component: 'pen',
title: `Simon Strange`,
key: `SimonStrangePen`
}
]
}
This JSON will be generated via a database call, and written each time the database is updated, and update the state of the 'catalog' component.
So, for example, the second object in the catalog array above is a container which, when the first 'pen' component is clicked, becomes visible and shows a list of 'world' components (in this case, just the one.) However, the function only successfully renders any 'parent' components--if I take out the curly braces at lines 24 and 26, it simply skips them but doesn't error.
The components are composed of button elements and a div (content). The buttons will likely become Link element when I get this working, but the original version was written in vanilla javascript, I haven't implemented routing with the catalog yet. So, the pen component for example:
import React from 'react'
export default penButton => {
return(
<button className="catalogItem pen">
<img src="src/icons/catPenName.png" className="catalogIcon"/>
<p className="contentLabel">{penButton.title}</p>
</button>
)
}
Is a top level component, and gets rendered just fine. It's next sibling (and the next sibling of any button except a book) is content:
import React from 'react'
export default contentList => {
return(
<div className="contentList">
</div>
)
}
contentList is just a div with the contentList class, which handles visibility and animation. Should I have a place for the "children" key in JSON to populate the children of content?
When you want to render multipile children elemen'ts into your react component, you need to pass each child as a seperate parameter.
See this answer as an example:
how to render multiple children without JSX
so your solution should be to use spread syntax.
here is an example:
const catalogRenderer = (config) => {
if (typeof KeysToComponentMap[config.component] !== "undefined") {
let childs = [];
if (config.children) {
childs = config.children.map(c => catalogRenderer(c));
}
return React.createElement(
KeysToComponentMap[config.component],
{
key: config.key,
title: config.title
},
...childs
);
}
}
Well, that was simple and a little silly. I updated the content component to:
import React from 'react'
export default contentList => {
return(
<div className="contentList">
{contentList.children} <---- added
</div>
)
}
Content didn't have a place to put children. Obviously.