Read multiple JSON files as one array - arrays

I currently have two JSON files that my array needs to read. Is there a way for me to read them as one array?
I've already tried putting both in a constant variable but it did not work. It was something like this which obviously is not the solution:
const var = [{json_file_1}, {json_file_2}];
I did also try lodash but I still didn't find the solution but I also have a console.log line for the code above.
console.log(_.flattenDeep(ThisFunction(var)));
ThisFunction() reads the contents of my json.
Here is my current array. It is only reading one json file:
const option = json_file_1
.map(group => (
<div key={group.title}>
<div>
{group.title}
</div>
{group.child_one.map(object => (
<div key={object.title}>
{object.title}
</div>
))
</div>
));
Both of JSON files go something like this:
[
{
"title": "this title",
"child_one": [
{
"content_1",
"content_2"
}
],
"child_two": [
{
"title" "this title",
"something": "something else"
},
{
"title" "this title",
"something": "something else"
}
]
}
]
The output should read the two files as one array. Once this is done, will I be able to integrate more JSON files to be read?

The reason you could't do it with
const var = [{json_file_1}, {json_file_2}];
is that you create two object in your array. However you can simply use spread operator.
So you can use it like this and pass this var to your component.
const var = [...json_file_1, ...json_file_2];
If couldn't explain it clearly please say so I can describe with more detail.

I might have found a solution but I don't believe this is the best since I am getting loads of console errors because some of my dummy data are the same
const var = [{json_file_1}, {jsone_file_2}];
and I passed it to my AutoComplete input
<AutoComplete onSearch={_.flattenDeep(ThisFunction(var))}></AutoComplete>
As mentioned above, ThisFunction() reads the arrays and nested arrays inside my JSON file

Related

Parse content of json in React

I've a response JSON which i would like to parse. Specifically, I am interested in visualizing in an HTML the values contained in the "raw".
Below is an example of the JSON file.
{
"values":{
"first":{
"raw":"first value",
"encoded":"1019570973946118"
},
"second":{
"raw":"second value",
"encoded":"1822871964691"
}
}
}
Using JSON.stringify I can see the entire JSON but, of course that is not my intention.
Thank you
Edit:
I'm sorry, I was very superficial in my initial description. I would like to extract the value contained in raw of this example json file and display it in a react component in HTML. Something like: {JSON.stringify(raw)}
Parsing a JSON string to an actual javascript object is NOT done by JSON.stringify() but by JSON.parse().
So in order to retrieve the raw part you would have to do this:
const response = `{
"values":{
"first":{
"raw":"first value",
"encoded":"1019570973946118"
},
"second":{
"raw":"second value",
"encoded":"1822871964691"
}
}
}`;
const parsedJSON = JSON.parse(response)
for (const key of parsedJSON.values.keys()) {
const raw = parsedJSON.values[key].raw;
console.log(raw)
}
The variable raw could be used as a prop, state, etc. now.

Why is Array.push() throwing an error but Array.concat() does not?

I am trying to add an array to an existing array. The initial data is like this:
props: {
ItemData: // This prop gets populated with data from the parent component. That data comes from a Vuex store.
{
type: Array,
default: null
}
}
setup(props) {
const Item = ref(props.ItemData);
onMounted( ()=> {
Form.Title = Item[0].Title
Form.Files = Item[0].Files
}
)
}
Which results in something like this:
Form = reactive({
Title: null,
Files: [
{name: "photo", extension: ".webp" size: '1024'},
{name: "doc", extension: ".pdf" size: '2048'}
]
)}
The data in Form.Files comes from a prop that is sent to this component from Vuex data:
Form.Files may also be an empty array [ ] if there are no existing files when the form is loaded.
When the user adds new files, the data for the new files is like this:
NewFiles = [
[
File,
{name: "newphoto", extension: ".jpg", size: "1024" }
],
[
File,
{name: "newdoc", extension: ".docx", size: "2048" }
]
]
File is the file object itself as selected via an input field e.g. <input multiple type="file" />
So how do we add NewFiles to Form.Files? I tried the following:
Form.Files.push(...NewFiles);
That somewhat works in that the Vue debugger shows the NewFiles array added to Form.Files, but it thrown an error of [vuex] do not mutate vuex store state outside mutation handlers. and the rest of the code fails.
So I tried concat() which works:
const AllFiles = Form.Files.concat(NewFiles);
Form.BroadcastFiles = AllFiles;
There's no errors but I don't understand why push() would cause a Vuex error when I'm not touching any Vuex state, and even if I was, why doesn't the contact() cause the same error?
.concat returns a new array with both the current items and the new ones where .push modifies the current array instead of returning a new one.
If that array was initially loaded from vuex it results in an unwanted mutation of the store.
Edit:
In the store
mutations: {
addFile(state, file) {
state.ItemData[0].Files.push(file);
},
}
In the component
NewFiles.forEach(file => store.commit("addFile", file));
I suggest you check this article about the use of spread operator in Javascript, and array reference How to Use the Spread Operator (…) in JavaScript especially the "A note about copying by reference" section. So basically you are mutating the state of Form.Files while using concat and you are losing the reference using the spread operator. One solution can be:
let AllFiles = [...Form.Files];
AllFiles.concat(NewFiles);
Form.BroadcastFiles = AllFiles;

How do I flatten the array and remove empty arrays from results of combineLatest(...)?

I’m working in an angular 6 application. I have a function that returns an observable of an array of observables, which in turn are observables of arrays.
The results might look something like this:
[
[],
[],
[object, object],
[],
[object],
[],
[object, object, object],
[]
]
As you can see, it’s an array of arrays and some arrays might be empty.
I’d like to list each object in each inner array on the page as follows:
<div *ngFor="let watcher of InvitationService.getInvitations() | async">
<div *ngFor="let invitation of watcher">
{{ invitation | json }}
</div>
</div>
And getInvitations() looks like this:
getInvitations() {
const groupedInvitations$: Observable<any>[] = [];
groups.forEach(group => {
const groupInvites$ = this._firestoreService.collection(`GroupInvitations/${group.groupID}/Invites`);
groupedInvitations$.push(groupInvites$);
});
Return Observable.combineLatest(groupedInvitations$);
}
What I’d like to do is remove the empty arrays from the results returned from combineLatest(…) and flatten the rest into a single one dimensional array.
I understand one can do this by piping through map(…) or flatMap(…) or things like that. But I’ve been trying things like that and nothing’s been working.
For example, I’ve tried this:
Return Observable.combineLatest(groupedInvitations$).pipe(
map(item => {
console.log(item);
});
);
But nothing gets logged to the console.
How can I flatten the array and remove empty arrays? Thanks.
Try using a filter first to remove the empty arrays and the use combineLatest to put them all together.
combineLatest(
groupedInvitations$.pipe(
filter(item => item.length > 0)
)
).pipe(
tap(item => { // Should be an array of arrays
console.log(item);
});
);
as I see it you can put an if condition before this line
groupedInvitations$.push(groupInvites$);
to check if the array length is greater than zero if yes add it to the returned array if not go to the next one
hope that helps

React JSX form field map fails if accessing certain properties

I'm attempting to build a form from an array of form fields where each form field looks like this:
{
"name": "state",
"resource": "customer",
"type": "TextBox",
"assetId": "State",
"label": {
"text": "State",
"assetId": "Label"
}
}
However, when I attempt to map it using JSX, the fields don't get successfully displayed if I access certain properties of the object. Take the following code, which functions correctly:
formfields.map(function (formfield, i) {
var returnfield = <div key={i}>{formfield.name}</div>;
switch (formfield.type) {
case "TextBox":
console.log(formfield.label);
returnfield = (
<div key={i}>
<label htmlFor="theinput">{formfield.name}</label>
<input id="theinput" type="text" value={formfield.name} />
</div>
);
break;
}
return returnfield;
});
And compare it with the code that fails:
formfields.map(function (formfield, i) {
var returnfield = <div key={i}>{formfield.name}</div>;
switch (formfield.type) {
case "TextBox":
console.log(formfield.label.text);
returnfield = (
<div key={i}>
<label htmlFor="theinput">{formfield.name}</label>
<input id="theinput" type="text" value={formfield.name} />
</div>
);
break;
}
return returnfield;
});
The astute observer will notice that the only difference between the two is that, in the second, we are logging formfield.label.text instead of formfield.label
I'm totally stumped why simply logging an object's grandchild attribute should cause the form to appear empty (i.e., with no fields). Perhaps I'm running into reserved names or something? Any ideas appreciated.
why didn't I see a javascript error in my developer console? Is there some weird thing where .map() doesn't allow errors to be raised?
After recognizing that checking for null is needed in your project well I suggest you use some concepts of javascript functional programming to compose a function that checks for falsely values before applying them in your logic.
You can use Maybe functor that returns a Maybe(null) which stops immediately. Before returning a null value to your logic and cause a boom!
You can also use Either, this is cool because it's just like maybe but you can also gve some logic to run if the value is falsely.
I have two examples for these suggestions (Copied from jsbin)
//Key container == Something map can iterate over like an object or an array.
//And am talking about the lodash / ramda.js curried map that can iterate over object not the js native one.
//Using Maybe
//Url http://jsbin.com/yumog/edit?js,console
var safeGet = _.curry(function(x,o){
return Maybe(o[x]);
//This will return Maybe(null)
//if it's some property in a container is not found
//which you can check before breaking something
});
var user = {id: 2, name: "Albert"}
var ex3 = compose(map(_.head), safeGet('name'));
assertDeepEqual(Maybe('A'), ex3(user))
console.log("exercise 3...ok!")
//Using Either.io
//url http://output.jsbin.com/bexuc/
// Write a function that uses checkActive()
//and showWelcome() to grant access or return the error
var showWelcome = compose(_.add( "Welcome "), _.get('name'))
//Here either returns a function you give it on the right if it's truthy
//and left if it's falsey (or falsy i don't know english .. )
// So you get to do something if the property in your container is not present.
var checkActive = function(user) {
return user.active ? Right(user) : Left('Your account is not active')
}
var ex1 = compose(map(showWelcome), checkActive);
assertDeepEqual(Left('Your account is not active'), ex1({active: false, name: 'Gary'}))
assertDeepEqual(Right('Welcome Theresa'), ex1({active: true, name: 'Theresa'}))
Links to the libraries.
Maybe: https://github.com/chrissrogers/maybe
Either: https://github.com/fantasyland/fantasy-eithers
You might also need to check on lodash / ramda to have a full idea on these functional concepts.

ReactJS - Listing all keys at once

I'm a beginner of ReactJS and I'm stuck trying to figure out why map only returns a single prop at a time.
In file1.jsx, I have an array that contains 3 objects:
var MainPanelOneData = [{"id":1,"shotviews":15080},{"id":2,"likes":12000},{"id":3,"comments":5100}];
File1.jsx also has a render function to extrapolate the data inside the array:
render: function() {
var ListMainPanelOne = MainPanelOneData.map(function(data) {
return <MainPanelOne key={data.key} shotviews={data.shotviews} likes={data.likes} comments={data.comments} />
});
In file2.jsx, I have this code to render the data object from file1.jsx:
render: function() {
return (
<div>
<span>{this.props.shotviews} shot views</span>
<span>{this.props.likes} likes</span>
<span>{this.props.comments} comments</span>
</div>
)
}
The result shows this:
15080 shot views likes comments
shot views12000 likes comments
shot views likes5100 comments
I'm guessing it repeats like this because it searches through one key at a time? If that's the case, how do I display all keys at the same time? Use indexing?
well your array of data doesnt have all the keys. each one of your objects in PanelOneData has ONE key and is missing the other two; additionally none of them have key called key. so youre making three MainPanelOne components, each with a single prop. the result of that map is this
[
<MainPanelOne key={null} shotviews={15080} likes={null} comments={null} />,
<MainPanelOne key={null} shotviews={null} likes={12000} comments={null} />,
<MainPanelOne key={null} shotviews={null} likes={null} comments={5100} />
]
which is an accurate display of what youre seeing
To get one line you might do something like this.
render: function() {
var ListMainPanelOne = MainPanelOneData.map(function(data) {
return <span key={data.id}> {data.shotviews} {data.likes} {data.comments} </span>
});

Resources