Calling a local json file and parsing data in ReactJS - json

I have the following json file. Right now, i have kept this in my ReactJS project itself locally. Later on planning to move in a server location.
abtestconfig.json
[
{
"abtestname": "expAButton",
"traffic": 1,
"slices":
[
"orange",
"blue"
]
},
{
"abtestname": "expTextArea",
"traffic": 0.5,
"slices":
[
"lightgrey",
"yellow"
]
}
]
I want to read and get data and parse it and apply in a function. I got some reference sample code and trying to use fetch api to react json file with the following code.
After reading this json file, i will have to pass the data in abtest function, as you can see now it's sending with hard coded value abtest('expAButton', 0.75).slices('orange', 'blue').run(function ()
I have the following doubts and wanted to get your guidance / clarification.
1. Is it correct way to read json file using fetch api? Is there any other best approach?
2. When I use fetch api like mentioned below, console log displays GET http://localhost:8080/abtesting/abtestconfig.json 404 (Not Found)
app.jsx file:
import './abtesting/abtestconfig.json';
class App extends React.Component {
constructor() {
super();
this.onClick = this.handleClick.bind(this);
this.onClickNewUser = this.handleNewUser.bind(this);
this.state = {
bgColor: '',
data: []
}
};
handleNewUser (event) {
abtest.clear();
window.location.reload();
}
render() {
return (
<Helmet
/>
<p><b>A/B Testing Experience</b></p>
<div className="DottedBox">
<p><button id = "newUserButton" onClick = {this.onClickNewUser} style={{backgroundColor:"red"}}>Welcome and click here</button></p>
</div>
);
}
handleClick () {
abtest('expAButton', 0.75).slices('orange', 'blue').run(function () {
expAButton.style.backgroundColor = this.slice.name;
});
}
setStyle (stylecolor) {
this.setState({
bgColor: stylecolor
})
}
componentDidMount () {
this.handleClick();
fetch('./abtesting/abtestconfig.json').then(response => {
console.log(response);
return response.json();
}).then(data => {
// Work with JSON data here
console.log(data);
}).catch(err => {
// Do something for an error here
console.log("Error Reading data " + err);
});
}
}
export default hot(module)(App);

Related

Accessing Vuex Store Before Page Load NuxtJS

Context: I am trying to get Google Maps place data via the place_id on the beforeEnter() route guard. Essentially, I want the data to load when someone enters the url exactly www.example.com/place/{place_id}. Currently, everything works directly when I use my autocomplete input and then enter the route but it does not work when I directly access the url from a fresh tab. I've been able to solve this using the beforeEnter() route guard in traditional Vue, but cannot solve for this using Nuxt. Please help!
Question: How can I access the Vuex Store before a page loads in Nuxt?
Error: Any solution I try (see below) I either end up with a blank page or the page will not load (I think it is stuck in a loop and cannot resolve the Promise).
Attempted Solutions:
Using Middleware like below:
middleware({ store, params }) {
return store.dispatch('myModule/fetchLocation', params.id)
}
Using asyncData like below:
data(){
return{
filteredLocation: {}
}
}
// snip
async asyncData({ store, params }) {
const { data } = await store.dispatch('myModule/fetchLocation', params.id)
return filteredLocation = data
}
I tried looking into fetch, but apparently you no longer have access to context
Example Code:
In one of my store modules:
/* global google */
import Vue from 'vue'
import * as VueGoogleMaps from '~/node_modules/vue2-google-maps/src/main'
Vue.use(VueGoogleMaps, {
load: {
key: process.env.VUE_APP_GMAP_KEY,
libraries: 'geometry,drawing,places'
}
})
export const state = () => ({
selectedLocation: {}
})
export const actions = {
fetchLocation({ commit }, params) {
return new Promise((resolve) => {
Vue.$gmapApiPromiseLazy().then(() => {
const request = {
placeId: params,
fields: [
'name',
'rating',
'formatted_phone_number',
'geometry',
'place_id',
'website',
'review',
'user_ratings_total',
'photo',
'vicinity',
'price_level'
]
}
const service = new google.maps.places.PlacesService(
document.createElement('div')
)
service.getDetails(request, function(place, status) {
if (status === 'OK') {
commit('SET_PLACE', place)
resolve()
}
})
})
})
}
}
export const mutations = {
SET_PLACE: (state, selection) => {
state.selectedInstructor = selection
}
}
EDIT: I already have it in a plugin named google-maps.js and in my nuxt.config.js file I have:
plugins: [
{ src: '~/plugins/google-maps.js' }
]
//
//
build: {
transpile: [/^vue2-google-maps.js($|\/)/],
extend(config, ctx) {}
}
Using Middleware is how we can access Vuex before page loads. try putting the configuration part in a custom Nuxt plugin.
Create a file in Plugins folder (you can name it global.js).
Put this
import Vue from 'vue'
import * as VueGoogleMaps from '~/node_modules/vue2-google-maps/src/main'
Vue.use(VueGoogleMaps, {
load: {
key: process.env.VUE_APP_GMAP_KEY,
libraries: 'geometry,drawing,places'
}
})
in global.js.
Then add the plugin in nuxt.config.js like this.
plugins: [
'~/plugins/global.js'
]
Also, make sure you're using underscore before 'page_id' name in your folder structure.

Vuejs getting data from local json

I got some json data in a local file the file is .txt file and the data is not directly accessible so I just changed the file format to .json and after that, I tried to get clean data to loop through with the code below.
I'm getting the data via computed in this component but I want to set this clean data as a prop to a child component.
I want to create many child components with clean data.
Thank you very much in advance!
Code:
<script>
export default {
name: 'Dashboard',
components : {
'my-table': mytable,
'my-search': search,
},
data: function() {
return {
casesDataList: [],
};
},
computed:{
ClearList: function(){
var casesDataList = this.casesDataList.map(function (neo){
return {ID: neo.Attributes[1].Value, Date: neo.FormattedValues[0].Value, Owner: neo.FormattedValues[1].Value};
});
return casesDataList;
}
},
created: function(){
this.getCasesData();
},
methods: {
getCasesData() {
fetch("Weather.json")
.then(response => response.json())
.then(data => (this.casesDataList = data.Entities));
},
}
};
</script>
You can pass the computed as a prop to the child directly:
<child :propname="ClearList"></child>
In the child:
export default {
props: ['propname'],
// ...
}

Data from API is displaying in the console but not in the DOM, why?

I'm learning React and a little about API's. I'm using the Destiny 2 API as a starting API to try to wrap my head around how they work.
Here is my Api.js file:
import React, { Component } from 'react';
import './style.css';
import axios from 'axios';
class Api extends Component {
constructor(props) {
super(props);
this.state = {
data: [],
};
}
componentDidMount() {
let config = {
headers: {
'X-API-KEY': 'key-here',
},
};
axios
.get('https://www.bungie.net/Platform/Destiny2/4/Profile/4611686018484544046/?components=100', config)
.then((response) => {
console.log(response);
this.setState({
data: response.data,
});
});
}
render() {
const { item } = this.state;
return (
<div>
{Array.isArray(item) &&
item.map((object) => <p key={object.data}>{object.data.Response.profile.data.userInfo.displayName}</p>)}
</div>
);
}
}
export default Api;
The data from the API is returned as an object that contains a nested array. I can get the data to display in the console no problem.
This is the layout of the response object output to the console:
I'm trying to grab the value of "displayName" and output it into the DOM, what am I doing wrong?
I have tried returning the data as JSON by doing:
response => {return(data.json())} and iterating through the json object using {Object.keys(this.state.data).map((key) => but I have still managed to only get data in the console and not in the DOM.
Is there anything that seems to be missing? I've been stuck with this problem for several days now!
EDIT: This is the whole response from the API call
{
"Response": {
"profile": {
"data": {
"userInfo": {
"membershipType": 4,
"membershipId": "4611686018484544046",
"displayName": "Snizzy"
},
"dateLastPlayed": "2019-04-05T14:28:30Z",
"versionsOwned": 31,
"characterIds": [
"2305843009409505097",
"2305843009411764917",
"2305843009425764024"
]
},
"privacy": 1
}
},
"ErrorCode": 1,
"ThrottleSeconds": 0,
"ErrorStatus": "Success",
"Message": "Ok",
"MessageData": {}
}
In the render function, where you destructure you state, you have the wrong property.
const { item } = this.state; should be const { data } = this.state;
More about destructuring here.
Also, you need to make changes here:
EDIT: Actually, your data isn't even an array. You don't have to iterate through it.
<div>
<p>{data.Response.profile.data.userInfo.displayName}</p>}
</div>
Let's do a check to make sure that we got back the api before running. You might be rendering before the api call is finished. Try using an inline statement.
{ item ? {Array.isArray(item) && item.map(object => (
<p key={object.data}>{object.data.Response.profile.data.userInfo.displayName}</p>
))}
:
<div>Loading...</div>

Posting a json data to my database with axios (using my backend api)

I have a very strange issue. I've got a backend api to import a json data to my mongodb.
On the screen I have a upload button to upload a file and I used react-dropzone for that. For example think that I have a file like "db.json" and in this file there is a json like as follows
{
"datapointtypes":[
{"id":"Wall plug","features":[{"providesRequires":"provides","id":"Binary switch"},{"providesRequires":"requires","id":"Binary sensor","min":"1","max":"2"}],"parameters":[{"id":"Communication type","type":"Communication type"}],"functions":[{"id":"Electricity"},{"id":"Switch"}]},
{"id":"Door sensor","features":[{"providesRequires":"provides","id":"Binary sensor"}],"parameters":[{"id":"Communication type","type":"Communication type"}],"functions":[{"id":"Door"},{"id":"Sensor"}]}
],
"datatypes":[
{"id":"Communication type","type":"enum","values":[{"id":"Zwave"},{"id":"Zigbee"}]},
{"id":"Zigbee network address","type":"decimal","min":1,"max":65336,"res":1},
{"id":"Serial port","type":"string"}
],
"features":[
{"id":"Zwave receiver","exposedtype":"Zwave command","functions":[{"id":"Communication"}]},
{"id":"Zigbee receiver","exposedtype":"Zigbee command","functions":[{"id":"Communication"}]},
{"id":"Binary switch","exposedtype":"On off state","functions":[{"id":"Actuator"}]},
{"id":"Binary sensor","exposedtype":"On off state","functions":[{"id":"Sensor"}]}
],
"servicetypes":[
{"id":"Room controller","datapointtype":"Room controller","DelayActive":false,"DelayValue":""},
{"id":"Xiaomi door sensor","datapointtype":"Door sensor","parameters":[{"id":"Zigbee network address","type":"Zigbee network address"},{"id":"Zigbee node id","type":"Zigbee node id"}],"parametervalues":[{"id":"Communication type","value":"Zigbee"}]}
],
"systems":[
{"id":"system 2","services":[{"serviceType":"Room controller","id":"servis 1"}],"serviceRelations":[{"serviceName":"servis 1","featureName":"Binary sensor"}],"parametervalues":[{"id":"Delay","paramName":"Delay","serviceType":"Room controller","value":"binary"}]},
{"id":"system 3","services":[{"serviceType":"Room controller","id":"servis 1"}],"serviceRelations":[{"serviceName":"servis 1","featureName":"Binary sensor"}],"katid":"7"}
]
}
The problem is this. If the browser console is open then my code is running succesfully and I can import the json data to my mongodb. But if browser console is closed I'm getting the "SyntaxError: Unexpected end of JSON input" error.
This is the function that I'm using on the import button
class FileUpload extends Component {
state = {
warning: ""
}
uploadFile = (files, rejectedFiles) => {
files.forEach(file => {
const reader = new FileReader();
reader.readAsBinaryString(file);
let fileContent = reader.result;
axios.post('http://localhost:3001/backendUrl', JSON.parse(fileContent),
{
headers: {
"Content-Type": "application/json"
}
})
.then(response => {
this.setState({warning: "Succeed"})
})
.catch(err => {
console.log(err)
});
});
}
render() {
return (
<div>
<Dropzone className="ignore" onDrop={this.uploadFile}>{this.props.children}
</Dropzone>
{this.state.warning ? <label style={{color: 'red'}}>{this.state.warning}</label> : null}
</div>
)
}
}
What is that I am doing something wrong or what causes this?
Can you help me?
Thank you
FileReader reads files asynchronously so you have to use a callback to access the results
I would use readAsText instead of readAsBinaryString in case there are non ascii characters in the JSON
Finally, JSON.parse converts a JSON string to an object(or whatever type it would be). fileContent is already JSON so leave it as is.
const reader = new FileReader();
reader.onlooad = (e) => {
let fileContent = this.result;
axios.post('http://localhost:3001/backendUrl', fileContent,
{
headers: {
"Content-Type": "application/json"
}
})
.then(response => {
this.setState({warning: "Succeed"})
})
.catch(err => {
console.log(err)
});
}
reader.readAsText(file);

How to efficiently fetch data from URL and read it with reactjs?

I have some URL with json and need to read data.
For the sake of this example json looks like this:
{
"results": [
...
],
"info": {
...
}
}
I want to return fetched data as a property of a component.
What is the best way to do it?
I tried to do that with axios. I managed to fetch data, but after setState in render() method I received an empty object. This is the code:
export default class MainPage extends React.Component {
constructor(props: any) {
super(props);
this.state = {
list: {},
};
}
public componentWillMount() {
axios.get(someURL)
.then( (response) => {
this.setState({list: response.data});
})
.catch( (error) => {
console.log("FAILED", error);
});
}
public render(): JSX.Element {
const {list}: any = this.state;
const data: IScheduler = list;
console.log(data); // empty state object
return (
<div className="main-page-container">
<MyTable data={data}/> // cannot return data
</div>
);
}
}
I don't have a clue why in render() method the data has gone. If I put
console.log(response.data);
in .then section, I get the data with status 200.
So I ask now if there is the other way to do that.
I would be grateful for any help.
----Updated----
In MyTable component I got an error after this:
const flightIndex: number
= data.results.findIndex((f) => f.name === result);
Error is:
Uncaught TypeError: Cannot read property 'findIndex' of undefined
What's wrong here? How to tell react this is not a property?
Before the request is returned, React will try to render your component. Then once the request is completed and the data is returned, react will re-render your component following the setState call.
The problem is that your code does not account for an empty/undefined data object. Just add a check, i.e.
if (data && data.results) {
data.results.findIndex(...);
} else {
// display some loading message
}
In React, after you have stored your ajax result in the state of the component (which you do appear to be doing), you can retrieve that result by calling this.state.list
So to make sure this is working properly, try <MyTable data={this.state.list}>
https://daveceddia.com/ajax-requests-in-react/