React output JSON from API - json

I have managed to get JSON from my api I have created, however I am having trouble actually rendering that JSON. I have managed to output it in the console by 'stringify'-ing it, however I cannot seem to actually render JSON to the page.
import React, { Component } from 'react';
import './App.css';
import $ from 'jquery';
function getData() {
return $.ajax({
type: "GET",
url: 'http://localhost:3001/data',
data: {},
xhrFields: {
withCredentials: false
},
crossDomain: true,
dataType: 'json',
success: handleData
});
}
function handleData(data /* , textStatus, jqXHR */ ) {
console.log(JSON.stringify(data));
return JSON.stringify(data);
}
class App extends Component {
render() {
return (
<div className="App">
<header>
<h2>Last Application Deployment </h2>
</header>
<div id='renderhere'>
{JSON.stringify(getData().done(handleData))}
</div>
</div>
);
}
}
export default App;

you cant execute a function in render method in return.you can use react lifecycles and store result in state like this =>
class App extends Component {
state = {result : null}
componentDidMount = ()=>{
$.ajax({
type: "GET",
url: 'http://localhost:3001/data',
data: {},
xhrFields: {
withCredentials: false
},
crossDomain: true,
dataType: 'json',
success: (result)=>{
this.setState({result : result});
}
});
};
render() {
return (
<div className="App">
<header>
<h2>Last Application Deployment </h2>
</header>
<div id='renderhere'>
{this.state.result && and what you want because i dont know why you want use JSON.stringfy - you use .map() or ...}
</div>
</div>
);
}
}
I suggest you see this article and this.

I've made a demo of how you can solve this: http://codepen.io/PiotrBerebecki/pen/amLxAw. The AJAX request should not be made in the render method but in a componentDidMount() lifecycle method. Also, it's best to store the response in state. Please see the guidance in the React docs: https://facebook.github.io/react/tips/initial-ajax.html
Fetch data in componentDidMount. When the response arrives, store the data in state, triggering a render to update your UI.
Here is the full code:
class App extends React.Component {
constructor() {
super();
this.state = {
time: '',
string: ''
};
}
componentDidMount() {
$.ajax({
type: "GET",
url: 'http://date.jsontest.com/'
})
.then(response => {
this.setState({
time: response.time,
string: JSON.stringify(response)
});
})
}
render() {
return (
<div className="App">
<header>
<h2>Last Application Deployment </h2>
</header>
<div id='renderhere'>
Time: {this.state.time} <br /><br />
String: {this.state.string}
</div>
</div>
);
}
}
ReactDOM.render(
<App />, document.getElementById('content')
);

Related

How to access values of JSON object which is bound to State of component in ReactJS

I am getting JSON data from WebService and I am initializing it to the state.
In UI, I want to directly bind a value to the textbox value field.
Here i was able to log the value of prod
But while binding the value to textbox I get error "Unable to get property of undefined or null reference":
import * as React from 'react';
import * as $ from "jquery";
interface IBudgetRequestReadOnly {
data: [any];
}
export class BudgetRequestReadOnly extends React.Component<{ RequestNumber }, IBudgetRequestReadOnly> {
constructor(props) {
super(props);
this.state = {
data: [{}],
};
}
componentDidMount() {
const RequestNumber = this.props.RequestNumber;
$.ajax({
type: "POST",
url: "Home/GetRequestByRequestID",
dataType: "json",
data: { requestID: RequestNumber },
success: function (msg) {
if (msg) {
this.setState({ data: msg });
console.log(this.state.data["product"].product);
}
}.bind(this),
error: function (msg) {
}
});
}
public render() {
return <div>
<div className="col-sm-12 Card ">
<div className="row"> </div>
<div className="row">
<div className="col-sm-12">
<label>Product Need<sup>*</sup></label>
<input type="text" className="form-control" aria-describedby="basic-addon1"
value={this.state.data["product"]} disabled />
</div>
</div>
<br />
</div>
</div >;
}
}
That's because your ajax request is asynchronous. Currently this is happening:
Your constructor is called.
render() is called
componentDidMount is called
The thing is that the render function you're trying to bind this.state.data.product.product but this doesn't exist (yet) on your first mount. Therefore trowing the error Unable to get property of undefined or null reference because this.state.data.product doesn't exist in this.state.data.
You could set a default value within your component state:
constructor(props) {
super(props);
this.state = {
data: {
product: {
product: '',
}
},
};
}
This will have this.state.data.product.product as an empty string by default, and upon obtaining your data from the API and updating the state, the actual data.product.product is set.
Now you can use <input value={this.state.data.product.product} /> without getting an error.

How to use Filter with ReactJS to prevent duplicates in an array from being displayed

I have a ReactJS page with three dropdown list, two of the dropdown list are displaying duplicate values. The values are being consumed from a json file. I researched using filter to remove the duplicates, but I'm unsure as to how I'm to apply it to my array when using React JS along with Fetch.
I created a function which employs the filter method, but I'm uncertain as to how I'm to implement it onto data: [], which contains the data consumed from the json file. This is the sample json file: https://api.myjson.com/bins/b1i6q
This is my code:
import React, { Component } from "react";
class Ast extends Component {
constructor() {
super();
this.state = {
data: [],
cfmRateFactor: "10"
};
} //end constructor
change = e => {
this.setState({
[e.target.name]: e.target.value
});
}; //end change
removeDups(array) {
return array.reduce((result, elem) => {
if (!result.some((e) => e.clientName === elem.clientName)) {
result.push(elem);
}
return result;
} , []);
}
componentWillMount() {
fetch("https://api.myjson.com/bins/b1i6q", {
method: "GET",
headers: {
Accept: "application/json",
"Content-type": "application/json"
}
/*body: JSON.stringify({
username: '{userName}',
password: '{password}'
})*/
}) /*end fetch */
.then(results => results.json())
.then(data => this.setState({ data: data }));
} //end life cycle
render() {
console.log(this.state.data);
return (
<div>
<div className="container">
<div className="astContainer">
<form>
<div>
<h2>Memeber Selection:</h2>
{["clientName", "siteName", "segmentName"].map(key => (
<div className="dropdown-padding">
<select key={key} className="custom-select">
{this.state.data.map(({ [key]: value }) => (
<option key={value}>{value}</option>
))}
</select>
</div>
))}
</div>
<div className="txt_cfm">
<label for="example-text-input">Modify CFM Rate Factor:</label>
<input
class="form-control"
type="textbox"
id="cfmRateFactor"
name="cfmRateFactor"
value={this.state.cfmRateFactor}
onChange={e => this.change(e)}
/>
</div>
<div>
<div>
<button type="submit" className="btn btn-primary">
Submit
</button>
</div>
</div>
</form>
</div>
</div>
</div>
);
}
}
export default Ast;
Could I please get some help with this? I'm still very new to using React JS.
You could use Map, it's a data structure for keeping key-value pairs. It will give you best performance for large data.
removeDuplicates(arr) {
const map = new Map();
arr.forEach(v => map.set(v.abc_buildingid, v)) // having `abc_buildingid` is always unique
return [...map.values()];
}
// this hook is better to start fetching data than componentWillMount
componentDidMount() {
fetch("https://api.myjson.com/bins/b1i6q", {
method: "GET",
headers: {
Accept: "application/json",
"Content-type": "application/json"
}
})
.then(results => results.json())
.then(data => this.setState({ data: this.removeDuplicates(data) })); // use the defined method
} //end life cycle
filter won't solve your problem. But reduce will.
You could have the following :
function removeDups(array) {
return array.reduce((result, elem) => {
if (!result.some((e) => e.abc_buildingid === element.abc_buildingid)) {
result.push(elem);
}
return result;
} , []);
}

Issue in accessing API/json with multiple sections

I'm trying to display all sections of the following json file into my reactjs page: https://api.myjson.com/bins/cdres
below is the code:
import React, { Component } from 'react';
import {render} from "react-dom";
class apps extends Component {
state = {
data: {
segments: [],
totals: [],
}
}
componentWillMount(){
fetch('https://api.myjson.com/file', {
method: 'GET',
headers: {
'Accept': 'application/json',
'Content-type': 'application/json',
'Authorization': 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJodHRwOi8vc2NoZW1hcy54bWxzb2FwLm9yZy93cy8yMDA1LzA1L2lkZW50aXR5L2NsYWltcy9uYW1lIjoiR3JlZyIsInVuaXF1ZV9uYW1lIjoiZ2dyYWZmIiwibmJmIjoxNTI0ODM5Nzc1LCJleHAiOjE1MjQ5MjYxNzV9.xhvdfaWkLVZ_HLwYQuPet_2vlxNF7AoYgX-XRufiOj0'
},
}
) /*end fetch */
.then(results => results.json())
.then(data => this.setState({ data: data }))
}
render() {
console.log(this.state.data);
return (
<div className="clientContainer">
{
this.state.data.segments.map( item =>(
<div>
<span> {item.clientName} </span>
</div>
))
}
{
this.state.data.totals.map(item =>(
<div>
<span> {item.segmentType} </span>
<span> {item.adjTotalSqrFt} </span>
</div>
))
}
</div>
);
}
}
export default app;
...the code works for consuming data from the segments and totals section of the json file, but am having trouble getting the id and username from the top section?
data is an object rather than an array so calling map on it triggers an error.
Simply do this.state.data.segments.map(...) instead, and change your initial state to
state = { data: { segments: [] } }
map is a function of array. The data is an object while data.segments is an array. You will need to change the code as below
<div className="clientContainer">
{
this.state.data.segments.map( item =>( //change here
<div>
<span> {item.clientName} </span>
</div>
))
}
</div>

Inserting object instead of string in MySQL in React/Express

I'm having troubles inserting data to MySQL from Express API Server, I'm getting the data from my React Client. I have 4 fields and one of them is not inserting correctly, you can see it in the below screen (the last 3 rows).
This is my client (React) code.
import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';
class App extends Component {
constructor(props) {
super(props);
this.state = {datos: {}};
this.onSubmit = this.handleSubmit.bind(this);
}
handleSubmit(e){
e.preventDefault();
var self = this;
// On submit of the form, send a POST request with the data to the server.
fetch('/todo/meterla',{
method: 'POST',
data:{
task: self.refs.task
}
})
.then(function(response){
return response.json()
}).then(function(body){
console.log(body);
});
}
render() {
return (
<div className="App">
<div className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<h2>Welcome to React</h2>
</div>
<form onSubmit={this.onSubmit}>
<input type="text" placeholder="TASK" ref="task"/>
<input type="submit"/>
</form>
</div>
);
}
}
export default App;
This is mi server code:
// Add a new todo
app.post('/todo/meterla', function (req, res) {
var task = req.body;
var query = mc.query("INSERT INTO tasks SET ? ", { task: task }, function (error, results, fields) {
});
});
In the client code, change data to body in the onSubmit handler:
fetch('/todo/meterla',{
method: 'POST',
body:{
task: self.refs.task
}
})
In the server code, change this line var task = req.body; to var task = req.body.task;.

React output JSON on new line

I am have managed to output the JSON from an API, however it is outputted in one large block, I however wish to display each piece of json on a new line everytime there is a closing '}'.
import React, { Component } from 'react';
import './App.css';
import $ from 'jquery';
class App extends Component {
state = {result : null}
componentDidMount = () => {
$.ajax({
type: "GET",
url: 'http://localhost:3001/data',
data: {},
xhrFields: {
withCredentials: false
},
crossDomain: true,
dataType: 'JSON',
success: (result) => {
this.setState({result : result});
}
});
};
render() {
return (
<div className="App">
<header>
<h2>Last Application Deployment </h2>
</header>
<div id='renderhere'>
{JSON.stringify(this.state.result)}
</div>
</div>
);
}
}
export default App;
try to wrap your text around this css style. and your issue will be solved. No complicated functions needed for this.
<p style={{whiteSpace: 'pre-line'}}>my json text goes here \n\n</p>
First option: if you want to output JSON for debugging purpose, you should try react-json-pretty
Second option: if what you trying to do is supposed to be for production do something like this:
<div id='renderhere'>
<pre>{JSON.stringify(this.state.result, null, 2)}</pre>
</div>