setState not working with import class component - reactjs

I have made a Class Component Token & import in App.js
In App.js, there is api having headers with Authorisation Key (i.e. Token)
I have tried this code so far
import React, {Component} from 'react';
import Token from './Token';
class App extends Component {
constructor(){
super();
this.state = { sliders: '', auth_key: ''};
}
componentWillMount(){
this.setState({
auth_key: <Token />
});
}
componentDidMount = () => {
//POST json
var dataToSend = { userid: '223' };
//POST request
fetch('API/PATH', {
method: 'POST', //Request Type
body: dataToSend, //post body
headers: {
'Content-Type': 'application/json',
'Authorization': this.state.auth_key
},
})
.then(response => response.json())
.then(responseJson => {
this.setState({ sliders: responseJson });
alert(JSON.stringify(responseJson));
})
.catch(error => {
console.error(error);
});
}
render(){
return this.state.sliders;
}
}
export default App;
this.state.auth_key in Authorisation not working. Please help to sort out this.
Token Component Class from which Token get passes to each component
import {Component} from "react";
export default class Token extends Component{
constructor(){
super();
this.state = {tokenid: ''};
}
componentDidMount = () => {
let formBody = { usertoken: '223' };
fetch('API/PATH', {
method: 'POST',
body: formBody,
})
.then(response => response.json())
.then(responseJson => {
this.setState({
'tokenid' : responseJson.authtoken
})
})
.catch(error => {
console.error(error);
this.setState({
'tokenid' : ''
})
});
}
render(){
return this.state.tokenid;
}
}

Related

API POST using fetch helper function doesn't render update after response is received

Beginner at React (and JS)...
I am trying to update text on the screen after my API helper function has completed a call. Instead, it returns empty. I have verified with the console that the data is being received. I followed the ComponentDidMount method from other similar questions but am still having no success. My code also seems to make multiple API calls, even though my intent is to only make one; I have to wonder if the issue stems from that.
Helper function:
export function apiHelper(url, data = {}, method = 'POST') {
return fetch(url, { // Return promise
method: method,
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data)
})
.then(res => res.json())
.then((result) => {
console.log(result);
return result;
}, (error) => {
error = error;
})
}
React Component that renders incorrectly after data is received:
class Headache extends React.Component {
constructor(props) {
super(props);
this.state = {
apiResponse: null,
};
}
componentDidMount() {
apiHelper(URLredacted,JSONredacted)
.then(response => {
this.setState({
apiResponse: response
});
console.log("state set.",response)
});
}
render() {
const jsonResponse = JSON.stringify(this.props.apiResponse)
return (
<div>
<img className="logoheader" src = {logo}/>
<ColoredLine color="grey"/>
<p>{jsonResponse}</p>
</div>
);
}
}
export function apiHelper(url, data = {}, method = 'POST') {
return fetch(url, { // Return promise
method: method,
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data)
})
.then(res => res.json())
.catch(err=>console.log(err))
}
second page:
class Headache extends React.Component {
constructor(props) {
super(props);
this.state = {
apiResponse: null,
};
}
componentDidMount() {
apiHelper(URLredacted,JSONredacted)
.then(response => {
this.setState({
apiResponse: response
});
console.log("state set.",response)
});
}
render() {
const jsonResponse = JSON.stringify(this.props.apiResponse)
return (
<div>
<img className="logoheader" src = {logo}/>
<ColoredLine color="grey"/>
<p>{jsonResponse && ""}</p>
</div>
);
}
}
if these code dont work you will be need asyn function because you need to wait to fetch data.

Error: Objects are not valid as a React child. If you meant to render a collection of children, use an array instead using Reactjs

How to solve this issue,Error: Objects are not valid as a React child (found: object with keys {cashback, image, logo, store_branches, store_id, store_name, store_summary, store_url}). If you meant to render a collection of children, use an array instead. I need **stores_list ** object data could you please help me.
My Component:
import React, { Component } from 'react';
import { Grid} from 'semantic-ui-react';
import { Link } from 'react-router-dom';
import OwlCarousel from 'react-owl-carousel';
export default class ApiData extends Component {
constructor(props) {
super(props);
this.state = {
data: [],
isLoading: true
};
}
async componentDidMount() {
const requestOptions = {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ title: 'React POST Request Example' })
};
const url = "https://localhost/api/v4/web/home";
fetch(url,requestOptions)
.then((response) => response.json())
.then((json) => {
this.setState({ data: json.sections.collections});
})
.catch((error) => console.error(error))
.finally(() => {
this.setState({ isLoading: false });
});
}
render() {
if (!this.state.data) {
return null;
}
var i=0;
var s;
if (i<this.state.data.length){
return s=this.state.data[i]["stores_list"];
i++
}
console.log(s)
return (
<Grid className='slider-three'>
</Grid>
);
}
};
my JSON:
collections": [
{
"home_offer_id": 71,
"stores_list": [
{
"cashback": "200",
"image": "https://dl8mjowvdz1rh.cloudfront.net/stores/Nara_Pan_Asis_Detail_1620125271937.jpeg",
"logo": "https://dl8mjowvdz1rh.cloudfront.net/stores/Nara_Pan_Asia_Logo_1620125267963.jpeg",
"store_branches": [
{
"store_city": "Dubai",
"store_location": "JLT"
}
],
"store_id": 120,
"store_name": "NARA Pan Asian",
"store_summary": "JLT, Brunch, Asian, Japanese, Thai, Chinese",
"store_url": "/store/nara-pan-asian/120"
}
]
}
]
}
You get that error when you try to return an {Object} instead of a [Array].
Reading your code it seems its likely coming from return s=this.state.data[i]["stores_list"];. Try using .map method to return an array of the results.
What you want to try to return should look like [{<Object>},{<Object>},{<Object>}]
import React, { Component } from 'react';
import { Grid} from 'semantic-ui-react';
import { Link } from 'react-router-dom';
import OwlCarousel from 'react-owl-carousel';
export default class ApiData extends Component {
constructor(props) {
super(props);
this.state = {
data: [],
isLoading: true
};
}
async componentDidMount() {
const requestOptions = {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ title: 'React POST Request Example' })
};
const url = "https://localhost/api/v4/web/home";
fetch(url,requestOptions)
.then((response) => response.json())
.then((json) => {
this.setState({ data: json.sections.collections});
})
.catch((error) => console.error(error))
.finally(() => {
this.setState({ isLoading: false });
});
}
render() {
if (!this.state.data){
return null;
}
const storesList = []
for (let index = 0; index < this.state.data.length; index++) {
const element = this.state.data[index];
storesList.push(element);
}
return (
<Grid className='slider-three'></Grid>
)
}
}
Try using the Array Instance Method .map() which expects a callback function. That callback function (store)=>store['stores_list'] is applied to each item and returns a brand new array for you in the storesList constant which is now an Array that looks like [{this.data[0]['stores_list']}, {this.data[1]['stores_list']}, {this.data[2]['stores_list']}, ..., {this.data[i]['stores_list']}] for i stores such that i === this.data.length.
Hopefully this helps

Method returning undefined even though fetch succeeds?

I have two components, Client and App, and a fetch function. App is the child component of Client. I want to update Client's state using the return value from the method App calls. However, Client's state response is undefined after the fetch. I'm not sure why this code does not work.
import React, { Component } from 'react';
import './App.css';
function post(user, token, data){
console.log('fetching...')
fetch(`/project`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Basic '+ btoa(user+':'+token),
},
body: JSON.stringify(data)
}).then(r => {
if (!r.ok)
throw Error(r.status);
r.json().then(r => {return(r)});
}).catch(error => {throw Error(error)})
}
class Client extends Component {
constructor(props) {
super(props);
this.state = {
user: '',
token: '111',
project: {'project':'demo'},
response: {},
};
this.updateState = this.updateState.bind(this);
};
updateState(){
const { user, token, project } = this.state;
post(user, token, project).then(text => this.setState({ response: text
}));
}
render() {
return (
<App updateState={this.updateState}/>
)
}
}
class App extends Component {
render() {
return (
<div className="App">
<button onClick={ () => {
this.props.updateState()} }>Fetch Project</button>
</div>
);
}
}
EDIT: I changed my post() to this and it works :)
async function post(user, token, data){
console.log('fetching...')
const response = await fetch(`/project`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Basic '+ btoa(user+':'+token),
},
body: JSON.stringify(data)
}).catch(error => {throw Error(error)});
if(!response.ok)
throw Error(response.status);
const obj = await response.json();
return(obj);
}
If you are working with promises, you can do something like this.
import React, { Component } from "react";
async function post() {
// fetch //
return await fetch("https://hipsum.co/api/?type=hipster-centric");
}
class Client extends Component {
constructor(props) {
super(props);
this.state = {
response: "12"
};
this.updateState = this.updateState.bind(this);
}
async updateState(res) {
const text = await res().then(res => res.text());
this.setState({ response: text });
}
render() {
return (
<>
{this.state.response}
<App updateState={this.updateState} />
</>
);
}
}
class App extends Component {
render() {
return (
<div>
<button
onClick={() => {
this.props.updateState(post);
}}
>
Fetch
</button>
</div>
);
}
}
export default Client;
sandbox
It will be nice to know all the code for the fetch function but I think the problem is mostly here:
this.props.updateState(post())
That call is synchronous and the fetching process isn't. You need a better approach with await or promises or a callback.

React JS - TypeError: this.state.data.map is not a function

Now i am trying to fatching data from API using axios and React JS. But when i use this code i got this error:
TypeError: this.state.countries.map is not a function
I have state data:[] and I am trying to set the values of URL in the state. So my code like this:
//get user token
const GetTokens = 'Bearer '.concat(localStorage.getItem('token'));
export default class Index extends Component {
constructor(props) {
super(props);
this.state = {
error: null,
countries: [],
response: {}
}
}
componentDidMount() {
axios.get(apiUrl + '/country-lists', { headers: { Authorization: GetTokens } })
.then(response => response.data).then(
(result) => {
this.setState({
countries: result
});
},
(error) => {
this.setState({ error });
}
)
}
And in my render like this:
{this.state.countries.map(list => (
{list.name}
))}
Also i tried like this.
render() {
const (countries ) = this.state
const (countries = []) = this.state
In my opinion, I made no mistake while getting a token and referencing the map. But I can't figure out where I made the mistake.
By looking at your console.log I think you should use result.data
componentDidMount() {
axios.get(apiUrl + '/country-lists', { headers: { Authorization: GetTokens } })
.then(response => response.data).then(
(result) => {
this.setState({
countries: result.data
});
},
(error) => {
this.setState({ error });
}
)

Implementing nested fetch API calls with setInterval for dashboard: fetch()+React+Typesctipt

I am trying to bring up a dashboard page with a react table. I want table to be refreshed every 2 seconds.Also I have two fetch api calls , where result of the first one is passed as a parameter to the second. Also second fetch call must set the chart data every two seconds.
Also if there are multiple tables that follows the same implementation of such fetch calls, how can I do it?
What is the better way to do it?
Help would be appreciated
import * as React from 'react';
import ReactTable from 'react-table';
import 'react-table/react-table.css';
interface IState {
data: any[];
}
export default class Dashboard extends React.Component<{},IState> {
constructor(props: any) {
super(props);
this.state = {
data: [],
}
componentDidMount()
{
const url="/api/query/fetch";
var result = fetch(url, {
method: 'post',
body : JSON.stringify({"id":"abc"),
headers: {
'Content-Type': 'application/json'
},
}).then(function(response) {
return response.json();
}).then(function(data) {
return fetch('api/query/fetch' + data.id); // want this call to be under setInterval such that chart data refreshes every 2 seconds, s uch that table data refreshes every 2 seconds
})
.then(function(response) {
return response.json();
})
.catch(function(error) {
console.log('Request failed', error)
})
result.then(function(r) {
this.setState({data:r});
});
}
render(){
return(
<ReactTable
data={this.state.data}
columns={columns} //column config object
/>
)
}
}
import * as React from 'react';
import ReactTable from 'react-table';
import 'react-table/react-table.css';
interface IState {
data: any[];
id: any;
}
export default class Dashboard extends React.Component<{}, IState> {
constructor(props: any) {
super(props);
this.state = {
data: [],
id: null
}
}
componentDidMount() {
const url = "/api/query/fetch";
fetch(
url,
{
method: 'post',
body: JSON.stringify({ "id": "abc"}),
headers: {
'Content-Type': 'application/json'
}
}
).then(function (response) {
return response.json();
}).then(function (data) {
this.setState({
id: data.id
}, () => this.fetchData())
});
}
fetchData() {
fetch('api/query/fetch' + this.state.id)
.then(function (response) {
return response.json();
})
.then(function (r) {
this.setState({ data: r });
setTimeout(() => {
this.fetchData();
}, 2000);
})
.catch(function (error) {
console.log('Request failed', error)
})
}
render(){
return (
<ReactTable
data={this.state.data}
columns={columns} //column config object
/>
)
}
}

Resources