Update deeply nested object property in immutableJS list - immutable.js

I've a following hierarchy of immutable list:
fromJS({
departments: [{
departmentName: 'PHP',
employees: [{
employeeId: 1000,
employeeName: 'Manish',
projects: [{
projectId: 200,
projectName: 'ABC'
},
{
projectId: 300,
projectName: 'DEF'
}]
}]
}]
})
In this list, I want to update the project name of project ID 200. Though I can update the simple one level of array of objects by finding their indexes but I don't have any idea that how to begin with this one in immutableJS.

I had something similar a long time ago... I used flatMap function. Eventually I modified my state structure as maintaining this code was a nightmare.
updateProduct = (id, newName, data) => {
return {
departments: Immutable.flatMap(data.departments, (department => {
return {
...department,
employees: Immutable.flatMap(department.employees, (employee => {
return {
...employee,
projects: Immutable.flatMap(employee.projects, (project => {
if (project.projectId == id) {
return {
...project,
projectName: newName
}
}
else {
return {...project}
}
}))
}
}))
}
}))
}
}

I believe the idiomatic way to do this with Immutable would be to use a lot of .map and .update calls:
const state = fromJS(/*...*/);
const newState = state.update('departments',
departments => departments.map(
department => department.update('employees',
employees => employees.map(
employee => employee.update('projects',
projects => projects.map(
project => project.get('projectId') === 200 ?
project.set('projectName', 'NEW_PROJECT_NAME') :
project
))))));
const state = Immutable.fromJS({
departments: [{
departmentName: 'PHP',
employees: [{
employeeId: 1000,
employeeName: 'Manish',
projects: [{
projectId: 200,
projectName: 'ABC'
},
{
projectId: 300,
projectName: 'DEF'
}
]
}]
}]
})
const newState = state.update('departments',
departments => departments.map(
department => department.update('employees',
employees => employees.map(
employee => employee.update('projects',
projects => projects.map(
project => project.get('projectId') === 200 ?
project.set('projectName', 'NEW_PROJECT_NAME') :
project
))))));
console.log(newState);
<script src="https://cdnjs.cloudflare.com/ajax/libs/immutable/3.8.2/immutable.min.js"></script>
Dealing with deeply nested data is annoying. I think you could make your life a lot simpler if you flattened your data structures a bit. Take this structure for example:
const state = fromJS({
departments: [{
employeeIds: [ 1000 ]
}],
employees: {
1000: {
employeeId: 1000,
employeeName: 'Manish',
projectIds: [ 200, 300 ]
}
},
projects: {
200: {
projectId: 200,
projectName: 'ABC'
},
300: {
projectId: 300,
projectName: 'DEF'
}
}
});
With a structure like this, the answer to your original question would be as easy as a single updateIn:
const newState = state.updateId(['projects', 200],
project => project.set('projectName', 'NEW_PROJECT_NAME'));

I recommend you either not using immutable.js for such complex data structures, or to refactor the structures to simple collections. Otherwise not only you would suffer from maintenance hell, but performance would be hundreds times worse (but still you might not notice it, depends on your app).

Related

Sequilize query is returning only one row while using include

Context : I am having this problem were I am doing a query using sequilize an it only return's me an array with one position even though I have more than one field that correspond to the query.
This are my two involved models
This is my group.js model
module.exports = (sequelize, DataTypes) => {
const Group = sequelize.define('Group', {
name: DataTypes.STRING,
limit: DataTypes.STRING,
user_id: DataTypes.INTEGER
});
Group.associate = models => {
Group.belongsTo(models.User, { foreignKey: 'user_id' });
};
Group.associate = models => {
Group.hasMany(models.Movement, { foreignKey: 'group_id' });
};
return Group;
}
This is my movement.js model
module.exports = (sequelize, DataTypes) => {
const Mov = sequelize.define('Movement', {
description: DataTypes.STRING,
value: DataTypes.INTEGER,
group_id: DataTypes.INTEGER
});
Mov.associate = models => {
Mov.hasOne(models.Group, { foreignKey: 'group_id' });
};
return Mov;
}
This is my query (where you will see that I am doing an INNER JOIN to SUM the fields of the Movement table)
router.get('/', verify, async (req, res) => {
try {
const group = await Group.findAll({
attributes: [
'id',
'name',
'limit',
[sequelize.fn('SUM', sequelize.col('Movements.value')), 'total_spent'],
],
include: [{
attributes: [], // this is empty because I want to hide the Movement object in this query (if I want to show the object just remove this)
model: Movement,
required: true
}],
where: {
user_id: req.userId
}
});
if (group.length === 0) return res.status(400).json({ error: "This user has no groups" })
res.status(200).json({ groups: group }) //TODO see why this is onyl return one row
} catch (error) {
console.log(error)
res.status(400).json({ Error: "Error while fetching the groups" });
}
});
Problem is that it only return's one position of the expected array :
{
"groups": [
{
"id": 9,
"name": "rgrgrg",
"limit": 3454354,
"total_spent": "2533"
}
]
}
It should return 2 positions
{
"groups": [
{
"id": 9,
"name": "rgrgrg",
"limit": 3454354,
"total_spent": "2533"
},
{
"id": 9,
"name": "rgrgrg",
"limit": 3454354,
"total_spent": "2533"
}
]
}
This is the query sequilize is giving me:
SELECT `Group`.`id`, `Group`.`name`, `Group`.`limit`, SUM(`Movements`.`value`) AS `total_spent` FROM `Groups` AS `Group` INNER JOIN `Movements` AS `Movements` ON `Group`.`id` = `Movements`.`group_id` WHERE `Group`.`user_id` = 1;
I guess you need to add an appropriate group by clause as follows -
const group = await Group.findAll({
attributes: [
'id',
'name',
'limit',
[sequelize.fn('SUM', sequelize.col('Movements.value')), 'total_spent'],
],
include: [{
attributes: [], // this is empty because I want to hide the Movement object in this query (if I want to show the object just remove this)
model: Movement,
required: true
}],
where: {
user_id: req.userId
},
group: '`Movements`.`group_id`'
});
Many-to-many "through" table with multiple rows of identical foreign key pairs only returns one result?
I just ran into this bug and added this options to the main query:
{
raw: true,
plain: false,
nest: true
}
Then you just merge the query.
It's a workaround, but might help someone.

Try to get key values recursively from JSON in Angular 5

I want to retrieve all the key values from a JSON file. For example in :
{
"total_count": 6,
"incomplete_results": false,
"items": [
{
"url": "https://api.github.com/repos/Samhot/GenIHM/issues/6",
"id": 293237635,
"number": 6,
"title": "Rechercher des documents",
"user": {
"login": "Samhot",
"id": 7148311
]
}
I would like to get :
["total_count", "incomplete_results", "items", "url", "url", "number", "title", "user", "login", "id"]
I have a function which return the content of my JSON in an observable :
getConfig(): Observable<any> {
return this.http.get<any>(this.myURL);
}
After that the data are reformated with .map to get only the keys with the Object.keys() function :
merge()
.pipe(
startWith({}),
switchMap(() => {
return this.getConfig();
}),
map(data => {
return Object.keys(data.items[0]);
}
)
)
.subscribe(data => {
this.dispo = data;
});
My problem is that i get only the keys that are in the level of the JSON I told
(data.items[0]) and not the ascendants or the descendants.
Of course I can create multiple requests but it asks to know in advance the structure of the JSON, what I want is to make it generic ...
How can I do to have an array with with all of my keys regardless of the structure of the JSON ?
Thanks in advance !
You would need to do a recursive function like:
function getDeepKeys(obj) {
const keys = Object.keys(obj);
const childKeys = keys
.map(key => obj[key])
.map(
value =>
Array.isArray(value)
? getDeepKeys(value[0])
: typeof value === "object"
? getDeepKeys(value)
: []
)
.reduce((acc, keys) => [...acc, ...keys], []);
return [...keys, ...childKeys];
}
const obj = {
total_count: 6,
incomplete_results: false,
items: [
{
url: "https://api.github.com/repos/Samhot/GenIHM/issues/6",
id: 293237635,
number: 6,
title: "Rechercher des documents",
user: {
login: "Samhot",
id: 7148311
}
},
{
url: "https://api.github.com/repos/Samhot/GenIHM/issues/6",
id: 293237635,
number: 6,
title: "Rechercher des documents",
user: {
login: "Samhot",
id: 7148311
}
}
]
};
console.log(getDeepKeys(obj));
Which then you would use like map(getDeepKeys). Note that this function assumes all the items in your array have the same schema.

How to name the fields of related model in filter object?

In my project, two models "UserProfile" and "UserAccount" are with a relation that the former "has one" the later. The .json files look like:
userprofile.json:
{
"name": "Userprofile",
"base": "PersistedModel",
//...
"properties": {
"userid": {
"type": "Number"
},
"phoneno": {
"type": "String"
}
},
//...
"relations": {
"userAccounts": {
"type": "hasOne",
"model": "UserAccount",
"foreignKey": "id",
"options": {
"validate": true,
"forceId": false
}
}
}
}
useraccount.json:
{
"name": "UserAccount",
"base": "User",
"idInjection": true,
"restrictResetPasswordTokenScope": true,
"emailVerificationRequired": true,
"properties": {},
"relations": {}
//...
}
The models have corresponding tables in a MariaDB.
Now the quest is to "GET" UserProfile with a keyword that match any one field of UserProfile.phoneno or UserAccount.email (yes, the key point is or). In SQL terms, that is:
SELECT * FROM UserProfile INNER JOIN UserAccount
ON UserProfile.userid = UserAccount.id
WHERE UserProfile.phoneno LIKE '%keyword%'
OR UserAccount.email LIKE '%keyword%'
It should be a common and simple query in SQL but seems become difficult in LookBack. My implementation is:
userprofile.js:
'use strict';
module.exports = function (Userprofile) {
Userprofile.remoteMethod('profileByEmailOrPhoneno', {
description: '...',
http: {path:'/profileByEmailOrPhoneno', verb: 'get'},
accepts: {arg: 'keyword', type: 'string', required: true},
returns: {arg: 'profile', type: 'array' }
})
Userprofile.profileByEmailOrPhoneno = function (keyword, cb) {
let filter = {
fields: {userid: true, nickname: true, phoneno: true},
include: {
relation: 'userAccounts',
scope: {
fields: {username: true, email: true}
}
},
where: {or: [
{phoneno: {like: `%${keyword}%`}},
{'userAccount.email': {like: `%${keyword}%`}}
]}
}
Userprofile.find(
filter,
function (err, records) {
if (err) console.log(err)
else cb(null, records)
}
)
}
};
I tested it on StrongLoop API Explorer and it always returned the whole records in UserProfile no matter whatever keyword. If the criterium
{'userAccount.email': {like: `%${keyword}%`}}
was removed the codes worked correctly. I think this criterium is wrong so LookBack ignores it and evaluate the where section to be true. I modified it to:
{'email': {like: `%${keyword}%`}}
and it was still wrong.
So, I wonder how to correctly name the relation model's field (eg.'email'), or, how to write the correct filter. Anybody can give some help? I'll very appreciated for it. ^^
The include statement in Loopback is a left-outer-join, so the query will always return ALL the Userprofile records. Some will have userAccounts with an array of values, other's wont. You need to further filter the Userprofile records.
Also, you need to put he userAccoutns filter in the scope statement of your filter:
Userprofile.profileByEmailOrPhoneno = function (keyword, cb) {
let filter = {
fields: {userid: true, nickname: true, phoneno: true},
include: {
relation: 'userAccounts',
scope: {
fields: {username: true, email: true},
where: {'email':{'like': `%${keyword}%`}} // userAccounts filter goes here
}
},
where: {phoneno: {like: `%${keyword}%`}}
}
Userprofile.find(filter, function (err, records) {
if (err) console.log(err)
else {
// filter the records for those that have userAccounts
var filteredResults = records.filter(record =>
record.userAccounts &&
Array.isArray(record.userAccounts()) &&
record.userAccounts().length);
cb(null, filteredResults)
}
})
}

Sequelize: multiple where clause

I have the following tables:
Article - User - Tag - Followers - Suscribes
Article belongs to User (fk: userId in Article table)
Article can have many tag. Here is the generated tagarticle table:
Here is followers table:
And the Suscribes table:
A user can follow many users and suscribe to a country(payId), a tag or an article(for notifications).
How to query all articles of followed users and suscribed country or tag for a specific user?
I assume that you ask about Sequelize way of doing the query.
I am not sure if I understand your question correctly. You are looking for two queries:
Query all articles of followed users,
Query subscribed country/tag/article of specific user,
Let me start with the associations made between the models.
// in User model definition
User.belongsToMany(User, { as: 'Followers', through: 'Followers', foreignKey: 'userId', otherKey: 'followId' });
User.hasMany(Subscribe, { foreignKey: 'userId' });
User.hasMany(Article, { foreignKey: 'userId' });
With use of above association we are now able to query all articles of followed users
models.User.findByPrimary(1, {
include: [
{
model: models.User,
as: 'Followers',
include: [ models.Article ]
}
]
}).then(function(user){
// here you have user with his followers and their articles
});
Above query would generate result similar to
{
id: 1,
Followers: [
{
id: 4,
Articles: [
{
id: 1,
title: 'article title' // some example field of Article model
}
]
}
]
}
If you want to query country/tag/article subscribed by specific user, you would have to make another associations in Subscribe model
// in Subscribe model definition
Subscribe.belongsTo(Tag, { foreignKey: 'tagId' });
Subscribe.belongsTo(Article, { foreignKey: 'articleId' });
Subscribe.belongsTo(Country, { foreignKey: 'payId' });
Now we have all the associations required to perform the second query you asked for
models.User.findByPrimary(1, {
include: [
{
model: models.Subscribe,
include: [ models.Tag, models.Country, models.Article ]
}
]
}).then(function(user){
// here you get user with his subscriptions
});
In this example you get user with all his subscriptions accessed via user.Subscribes, which will have nested attributes Tag, Country and Article. If user subscribed to Tag, both Country and Article would be NULL in this case.
Minimal runnable example of getting articles by followed users with assertions
https://stackoverflow.com/a/42634024/895245 was correct, here is a runnable version of it, also covering some other related functionality like limit and ordering. Further examples of interest at: How to implement many to many association in sequelize tested on:
npm install sequelize#6.5.1 sqlite3#5.0.2
Source:
#!/usr/bin/env node
const assert = require('assert');
const path = require('path');
const { Sequelize, DataTypes } = require('sequelize');
const sequelize = new Sequelize({
dialect: 'sqlite',
storage: 'db.sqlite3',
});
(async () => {
// Create the tables.
const User = sequelize.define('User', {
name: { type: DataTypes.STRING },
}, {});
const Post = sequelize.define('Post', {
body: { type: DataTypes.STRING },
}, {});
User.belongsToMany(User, {through: 'UserFollowUser', as: 'Follows'});
User.hasMany(Post);
Post.belongsTo(User);
await sequelize.sync({force: true});
// Create data.
const users = await User.bulkCreate([
{name: 'user0'},
{name: 'user1'},
{name: 'user2'},
{name: 'user3'},
])
const posts = await Post.bulkCreate([
{body: 'body00', UserId: users[0].id},
{body: 'body11', UserId: users[0].id},
{body: 'body10', UserId: users[1].id},
{body: 'body11', UserId: users[1].id},
{body: 'body20', UserId: users[2].id},
{body: 'body21', UserId: users[2].id},
{body: 'body30', UserId: users[3].id},
{body: 'body31', UserId: users[3].id},
])
await users[0].addFollows([users[1], users[2]])
// Get all posts by authors that user0 follows.
// The posts are placed inside their respetive authors under .Posts
// so we loop to gather all of them.
{
const user0Follows = (await User.findByPk(users[0].id, {
include: [
{
model: User,
as: 'Follows',
include: [
{
model: Post,
}
],
},
],
})).Follows
const postsFound = []
for (const followedUser of user0Follows) {
postsFound.push(...followedUser.Posts)
}
postsFound.sort((x, y) => { return x.body < y.body ? -1 : x.body > y.body ? 1 : 0 })
assert(postsFound[0].body === 'body10')
assert(postsFound[1].body === 'body11')
assert(postsFound[2].body === 'body20')
assert(postsFound[3].body === 'body21')
assert(postsFound.length === 4)
}
// With ordering, offset and limit.
// The posts are placed inside their respetive authors under .Posts
// The only difference is that posts that we didn't select got removed.
{
const user0Follows = (await User.findByPk(users[0].id, {
offset: 1,
limit: 2,
// TODO why is this needed? It does try to make a subquery otherwise, and then it doesn't work.
// https://selleo.com/til/posts/ddesmudzmi-offset-pagination-with-subquery-in-sequelize-
subQuery: false,
include: [
{
model: User,
as: 'Follows',
include: [
{
model: Post,
}
],
},
],
})).Follows
assert(user0Follows[0].name === 'user1')
assert(user0Follows[1].name === 'user2')
assert(user0Follows.length === 2)
const postsFound = []
for (const followedUser of user0Follows) {
postsFound.push(...followedUser.Posts)
}
postsFound.sort((x, y) => { return x.body < y.body ? -1 : x.body > y.body ? 1 : 0 })
// Note that what happens is that some of the
assert(postsFound[0].body === 'body11')
assert(postsFound[1].body === 'body20')
assert(postsFound.length === 2)
// Same as above, but now with DESC ordering.
{
const user0Follows = (await User.findByPk(users[0].id, {
order: [[
{model: User, as: 'Follows'},
Post,
'body',
'DESC'
]],
offset: 1,
limit: 2,
subQuery: false,
include: [
{
model: User,
as: 'Follows',
include: [
{
model: Post,
}
],
},
],
})).Follows
// Note how user ordering is also reversed from an ASC.
// it likely takes the use that has the first post.
assert(user0Follows[0].name === 'user2')
assert(user0Follows[1].name === 'user1')
assert(user0Follows.length === 2)
const postsFound = []
for (const followedUser of user0Follows) {
postsFound.push(...followedUser.Posts)
}
// In this very specific data case, this would not be needed.
// because user2 has the second post body and user1 has the first
// alphabetically.
postsFound.sort((x, y) => { return x.body < y.body ? 1 : x.body > y.body ? -1 : 0 })
// Note that what happens is that some of the
assert(postsFound[0].body === 'body20')
assert(postsFound[1].body === 'body11')
assert(postsFound.length === 2)
}
// Here user2 would have no post hits due to the limit,
// so it is entirely pruned from the user list as desired.
// Otherwise we would fetch a lot of unwanted user data
// in a large database.
const user0FollowsLimit2 = (await User.findByPk(users[0].id, {
limit: 2,
subQuery: false,
include: [
{
model: User,
as: 'Follows',
include: [ { model: Post } ],
},
],
})).Follows
assert(user0FollowsLimit2[0].name === 'user1')
assert(user0FollowsLimit2.length === 1)
// Case in which our post-sorting is needed.
// TODO: possible to get sequelize to do this for us by returning
// a flat array directly?
// It's not big deal since the LIMITed result should be small,
// but feels wasteful.
// https://stackoverflow.com/questions/41502699/return-flat-object-from-sequelize-with-association
// https://github.com/sequelize/sequelize/issues/4419
{
await Post.truncate({restartIdentity: true})
const posts = await Post.bulkCreate([
{body: 'body0', UserId: users[0].id},
{body: 'body1', UserId: users[1].id},
{body: 'body2', UserId: users[2].id},
{body: 'body3', UserId: users[3].id},
{body: 'body4', UserId: users[0].id},
{body: 'body5', UserId: users[1].id},
{body: 'body6', UserId: users[2].id},
{body: 'body7', UserId: users[3].id},
])
const user0Follows = (await User.findByPk(users[0].id, {
order: [[
{model: User, as: 'Follows'},
Post,
'body',
'DESC'
]],
subQuery: false,
include: [
{
model: User,
as: 'Follows',
include: [
{
model: Post,
}
],
},
],
})).Follows
assert(user0Follows[0].name === 'user2')
assert(user0Follows[1].name === 'user1')
assert(user0Follows.length === 2)
const postsFound = []
for (const followedUser of user0Follows) {
postsFound.push(...followedUser.Posts)
}
// We need this here, otherwise we would get all user2 posts first:
// body6, body2, body5, body1
postsFound.sort((x, y) => { return x.body < y.body ? 1 : x.body > y.body ? -1 : 0 })
assert(postsFound[0].body === 'body6')
assert(postsFound[1].body === 'body5')
assert(postsFound[2].body === 'body2')
assert(postsFound[3].body === 'body1')
assert(postsFound.length === 4)
}
}
await sequelize.close();
})();
Super many to many to do the "posts by followed users" query without post processing
Super many to many means explicitly setting belongsTo/hasMany between each model and the through table, in addition to the belongsToMany of each model.
This is the only way I found to nicely make the "posts by followed users" query without post processing.
const assert = require('assert');
const path = require('path');
const { Sequelize, DataTypes, Op } = require('sequelize');
const sequelize = new Sequelize({
dialect: 'sqlite',
storage: 'tmp.' + path.basename(__filename) + '.sqlite',
define: {
timestamps: false
},
});
(async () => {
// Create the tables.
const User = sequelize.define('User', {
name: { type: DataTypes.STRING },
});
const Post = sequelize.define('Post', {
body: { type: DataTypes.STRING },
});
const UserFollowUser = sequelize.define('UserFollowUser', {
UserId: {
type: DataTypes.INTEGER,
references: {
model: User,
key: 'id'
}
},
FollowId: {
type: DataTypes.INTEGER,
references: {
model: User,
key: 'id'
}
},
}
);
// Super many to many.
User.belongsToMany(User, {through: UserFollowUser, as: 'Follows'});
UserFollowUser.belongsTo(User)
User.hasMany(UserFollowUser)
User.hasMany(Post);
Post.belongsTo(User);
await sequelize.sync({force: true});
// Create data.
const users = await User.bulkCreate([
{name: 'user0'},
{name: 'user1'},
{name: 'user2'},
{name: 'user3'},
])
const posts = await Post.bulkCreate([
{body: 'body0', UserId: users[0].id},
{body: 'body1', UserId: users[1].id},
{body: 'body2', UserId: users[2].id},
{body: 'body3', UserId: users[3].id},
{body: 'body4', UserId: users[0].id},
{body: 'body5', UserId: users[1].id},
{body: 'body6', UserId: users[2].id},
{body: 'body7', UserId: users[3].id},
])
await users[0].addFollows([users[1], users[2]])
// Get all the posts by authors that user0 follows.
// without any post process sorting. We only managed to to this
// with a super many to many, because that allows us to specify
// a reversed order in the through table with `on`, since we need to
// match with `FollowId` and not `UserId`.
{
const postsFound = await Post.findAll({
order: [[
'body',
'DESC'
]],
include: [
{
model: User,
attributes: [],
required: true,
include: [
{
model: UserFollowUser,
on: {
FollowId: {[Op.col]: 'User.id' },
},
attributes: [],
where: {UserId: users[0].id},
}
],
},
],
})
assert.strictEqual(postsFound[0].body, 'body6')
assert.strictEqual(postsFound[1].body, 'body5')
assert.strictEqual(postsFound[2].body, 'body2')
assert.strictEqual(postsFound[3].body, 'body1')
assert.strictEqual(postsFound.length, 4)
}
await sequelize.close();
})();

Getting json object data with react

I am attempting to pull data out of json like this, which is imported as "values"
{
"content": {
"person": [
{
"name": "Test"
"age" : "24:
}
]
}
}
I am using .map like below but getting the error .default.map is not a function I believe it is because i have objects not arrays, i've tried a bunch of stuff including object.keys but i'm getting errors all over the place, any direction would be appreciated.
import values from './sample.json'
const vals = values.map((myval, index) => {
const items = person.items.map((item, i) => {
return (
<div>{item.name}</div>
)
})
return (
<div>{items}</div>
)
})
I think your data and code have some errors. But after fixing those and also changing the name from 'person' to 'people' if that's what you are after, here's the code that does what you are trying to do:
var data = {
content: {
people: [
{
name: "Test",
age: 24,
},
{
name: "Foo",
age: 25,
},
],
},
};
var App = React.createClass({
render: function () {
var people = data.content.people.map(function (person) {
return <div>{person.name}</div>;
});
return <div>{people}</div>;
},
});
ReactDOM.render(<App />, document.getElementById("app"));
And here's the JSBin for that: https://jsbin.com/coyalec/2/edit?html,js,output
Update: I'm updating the answer with more detailed example. It now deals with data more generically, like it doesn't assume what are the entries of 'contents' and such, but it knows that each type like 'people' or 'pets' are an array.
var data = {
content: {
people: [
{
name: "Test",
age: 24,
},
{
name: "Foo",
age: 25,
},
],
pets: [
{
name: "Sweety",
age: 3,
},
{
name: "Kitty",
age: 5,
},
],
},
};
var App = React.createClass({
render: function () {
// Get the keys in data.content. This will return ['people', 'pets']
var contentKeys = Object.keys(data.content);
// Now start iterating through these keys and use those keys to
// retrieve the underlying arrays and then extract the name field
var allNames = contentKeys.map((t) =>
data.content[t].map((e) => <div>{e.name}</div>)
);
return <div>{allNames}</div>;
},
});
ReactDOM.render(<App />, document.getElementById("app"));
And here's the latest JSBin: https://jsbin.com/coyalec/4/edit?html,js,output