how to use map function with (axios/classhooks) to read from API - reactjs

import React, { Component } from "react";
import axios from "axios";
class Verifry extends Component {
constructor(props) {
super(props);
this.state = {
s: "0",
user: [],
};
}
/* has title as attribute within the res.data*/
async componentDidMount() {
await axios
.get(http://10.0.0.106:8080/kuwait_elections/api/about_us)
.then((res) => {
const persons = res.data;
this.setState({ user: persons.data.title, s: "4" });
console.log(this.state.user);
});
}
componentDidUpdate() {
// this.state.user.map((u) => {
// return u;
// });
}
render() {
return (
{this.state.user.map((t) => {
return {t.title};
})}
);
}
}
export default Verifry;

Seems your return is not correct. It should be like this.
{
this.state.user.map(({title}) => {
return { title };
})
}
Note: Please format your code properly to make it easier to understand.

Related

Type error: Cannot read property 'map' of undefined

import React, { Component } from "react";
import axios from "axios";
class Abc extends Component {
constructor(props) {
super(props);
this.state = { descriptions: [] };
}
componentDidMount() {
axios
.get("https://jsonplaceholder.typicode.com/users")
.then(response => {
this.setState({ descriptions: response.data });
if (response.data) {
var rdata = response.data;
for (var r = 0; r < rdata.length; r++) {
if (r === 0) {
// console.log(rdata[r]);
// const {rdata} this.dataEle = rdata[r]
console.log(this.dataEle.name);
}
}
}
})
.catch(error => {
console.log(error);
});
}
render() {
const { dataEle } = this.setState;
return (
<div>
{dataEle.map((description, index) => (
<p key={index}>{description.description}</p>
))}
</div>
);
}
}
export default Abc;
dataEle is undefined in the first render (and any subsequent renders before it is fetched). You also don't destructure it correctly in your render function. I think you likely meant to destructure descriptions instead.
import React, { Component } from "react";
import axios from "axios";
class Abc extends Component {
constructor(props) {
super(props);
this.state = {
descriptions: [],
};
}
componentDidMount() {
axios
.get("https://jsonplaceholder.typicode.com/users")
.then(response => {
this.setState({ descriptions: response.data });
// if (response.data) {
// var rdata = response.data;
// for (var r = 0; r < rdata.length; r++) {
// if (r === 0) {
// // console.log(rdata[r]);
// // const {rdata} this.dataEle = rdata[r]
// console.log(this.dataEle.name);
// }
// }
// }
})
.catch(error => {
console.log(error);
});
}
render() {
const { descriptions } = this.state;
return (
<div>
// {descriptions.map((description, index) => (
// <p key={index}>{description.description}</p> // response data objects don't have a description property!
// ))}
{descriptions[1] && descriptions[1].name}
</div>
);
}
}
export default Abc;
Also, the response data shape doesn't have a description property on it, but TBH I'm not really sure what you're even trying to do with the for-loop, it throws an error.
Quite a few problems in your code.
Presumably you intended:
const { dataEle } = this.setState;
to be
const { descriptions = [] } = this.state;
Please try that:
class Abc extends Component {
constructor(props) {
super(props);
this.state = {
descriptions: [] ;
}
}
componentDidMount() {
axios
.get("https://jsonplaceholder.typicode.com/users")
.then(response => {
this.setState({ descriptions: response.data });
})
.catch(error => {
console.log(error);
});
}
//for mapping**
return (
<div>
{this.sate.descriptions.map((description, index) => (
<p key={index}>{description.description}</p>
))}
</div>
);
}
}

Data from Axios is coming back undefined React

My GET request with axios returns back undefined in my console. All of my endpoints are good and
working from being tested with postman. My initial state go from pets: [] to pets: "". I think it's how I have my async await function set up to get the response data.
Here's the GET Component code
import React, {
Component
}
from 'react';
import axios from 'axios';
export default class ListPets extends Component {
constructor(props) {
super(props);
this.state = {
pets: [],
isLoaded: false,
}
}
componentDidMount = () => {
this.getPets();
};
getPets = async() => {
const res = await axios.get('http://localhost:5000/pets/');
const pets = res.data;
this.setState({
isLoaded: true,
pets: pets
});
console.log('Data has been received!');
console.log(pets.data)
return pets;
}
render() {
console.log('State: ', this.state);
const {
isLoaded,
} = this.state;
if (!isLoaded) {
return <div> Loading... </div>;
} else {
return (<div></div>);
}
}
}
app.get('/pets', function(req, res){
const resultArray = [];
client.connect(err => {
assert.equal(null, err);
console.log("Connected successfully to server");
const db = client.db(dbName);
const cursor = db.collection('pet').find({});
iterateFunc = (doc,err) => {
assert.equal(null, err);
resultArray.push(doc);
console.log(JSON.stringify(doc, null, 4));
if(err) {
console.log(err)
}
}
cursor.forEach(iterateFunc);
client.close();
res.render('index', {pets: resultArray});
});
});
Your code can only render a Loading message but if the problem is the empty string then my guess is your API is returning an empty string.
Here's your code, slightly modified but working with a JSONPlaceholder API: https://codesandbox.io/s/compassionate-faraday-h9xpg
export default class ListPets extends Component {
constructor(props) {
super(props);
this.state = {
pets: [],
isLoaded: false
};
}
componentDidMount = () => {
this.getPets();
};
getPets = async () => {
const res = await axios.get("https://jsonplaceholder.typicode.com/todos");
const pets = res.data;
this.setState({ isLoaded: true, pets: pets });
};
render() {
const { isLoaded, pets } = this.state;
if (!isLoaded) {
return <div>Loading...</div>;
}
return <>{pets && pets.map(pet => <div key={pet.id}>{pet.title}</div>)}</>;
}
}

this.state is giving null after api call

I am consoling state right after my function call in componentDidMount but it's giving data as EMPTY String.
import React, { Component } from "react";
class App extends Component {
constructor(props) {
super(props);
this.state = {
data: ""
};
}
getData = () => {
functionApiCall().then(res => {
this.setState({
data: res.data
}); // Here the state is getting set
})
}
componentDidMount() {
this.getData();
console.log(this.state.data); //Empty string
}
render() {
return <></>;
}
}
export default App;
Any help will be appreciated.Thank you
Well, I think the api call is returning null , maybe change it like this
getData = () => {
functionApiCall().then(res => {
if(res && res.data) {
this.setState({
data: res.data
})// Here the state is getting set
}
}
}
Above should be fine, but just in case try this
getData = () => {
return new Promise(function(resolve, reject) {
functionApiCall().then(res => {
if(res && res.data) {
this.setState({
data: res.data
}, () => { resolve(res.data) })// Here the state is getting set
}
} });
}
And componentDidMount wait for your promise which resolves after state is set
async componentDidMount(){
await this.getData();
console.log(this.state.data) //NULL
}
setState is asynchronous so you cannot immediately access it.
You can render conditionally like this:
class App extends Component {
constructor(props) {
super(props);
this.state = {
data: null
};
}
getData = () => {
functionApiCall().then(res => {
this.setState({
data: res.data
});
});
};
componentDidMount() {
this.getData();
}
render() {
if (!this.state.data) {
return <div>Loading...</div>;
} else {
return <div>Data: {JSON.stringify(this.state.data)}</div>;
}
}
}
export default App;
Sample codesandbox with a fake api

React component doesn't update after updating state with redux action

/keywordsActions
import { UPDATE_KEYWORDS } from "./actionTypes";
import queryString from "query-string";
const keywordsArrayFromUrl = () => {
const query = queryString.parse(window.location.search);
if (query.keywords) {
const removeDuplicate = new Set(query.keywords.split(" "));
return Array.from(removeDuplicate);
}
return [];
};
export function updateKeywords() {
return async dispatch => {
dispatch({
type: UPDATE_KEYWORDS,
payload: await keywordsArrayFromUrl()
});
};
}
/keywordReducer
import { UPDATE_KEYWORDS } from "../actions/actionTypes";
export default function(state = [], action) {
switch (action.type) {
case UPDATE_KEYWORDS:
return action.payload;
default:
return state;
}
}
/SearchBar -- React Component
import React, { Component } from "react";
import { withRouter } from "react-router-dom";
//Redux
import { connect } from "react-redux";
import { updateKeywords } from "../store/actions/KeywordsAction";
class Searchbar extends Component {
constructor(props) {
super(props);
this.state = {
keywords : this.props.keywords
keywordsString: this.props.keywords.join(" ")
};
}
componentDidMount() {
this.props.updateKeywords();
console.log(this.props)
setTimeout(() => console.log(this.props), 10);
}
_handleChange = e => {
this.setState({ keywordsString: e.target.value });
};
_handleSearch = value => {
this.setState({ keywordsString: value });
this.props.history.push(`/search?keywords=${value}`);
};
render() {
return (
<Search
className="Searchbar"
placeholder="Cauta prin iBac..."
value={this.state.keywordsString}
onChange={this._handleChange}
onSearch={this._handleSearch}
/>
);
}
}
const mapStateToProps = state => {
return {
keywords: state.keywords
};
};
export default connect(
mapStateToProps,
{ updateKeywords }
)(withRouter(Searchbar));
I want to save the keywords from the Url to the store and then pass it to the Search bar state.
But i dont understand this :
componentDidMount() {
this.props.updateKeywords();
console.log(this.props); // this.props.keywords is empty
setTimeout(() => console.log(this.props), 10); // After 10 ms this.props.keywords is no empty
}
After 10 ms the props of Searchbar gets updated but the component doesn't render again.
Sorry for my question, I am really new to React / Redux. Please let me know what I am doing wrong. Thank you all!
Update :
componentDidMount() {
this.props.updateKeywords();
setTimeout(() => {
this.setState({
keywordsString: this.props.keywords.join(" ")
});
}, 0);
}
This code is also working... but this other is not working
componentDidMount() {
this.props.updateKeywords();
this.setState({
keywordsString: this.props.keywords.join(" ")
});
}
The reason is that componentDidMount is only called once on mount. What you're looking for is either componentShouldUpdate or componentDidUpdate or the render function, all of which are called when your component receives the updated state from redux. You can read here for more information on what these functions do.
https://reactjs.org/docs/react-component.html#updating

Change data on navbar when logout and login with another account

Aim :
I want to put firstName and lastName on my Navbar. So, I'm using axios request by id with userId
EDIT: Thanks to #Isaac, I have no more infinite loop when I'm using componentWillUpdate() now.
Problem : Data doesn't change (firstName and lastName) when I'm logout and login with another account
No problems from servers.
here a picture :
Description : I've login as a & g (firstName and lastName), then I've logout and login as j & j.
navbar.js:
import React, { Component } from 'react';
import { fade } from '#material-ui/core/styles/colorManipulator';
import { withStyles } from '#material-ui/core/styles';
import { connect } from 'react-redux';
import AuthA from '../store/actions/AuthA';
import { withRouter } from 'react-router-dom';
import '../Navbar.css';
import NavbarV from './NavbarV';
import PropTypes from 'prop-types';
import axios from 'axios';
class NavbarC extends Component {
constructor(props){
super(props);
this.state = {
client:[]
}
}
componentWillMount(){
this.getUser();
}
getUser(){
axios.get (`http://localhost:3002/api/clients/${localStorage.getItem("userId")}?access_token=${localStorage.getItem("token")}`)
.then(res => {
this.setState({client: res.data}, () => {
console.log(this.state)
})
})
}
shouldComponentUpdate(nextState){
return (this.state.client.firstName !== nextState.firstName ||
this.state.client.lastName !== nextState.lastName);
}
componentWillUpdate(){
this.getUser();
console.log(this.state)
}
logout = () => {
this.props.authfn.logout();
};
render() {
return(
<NavbarV logout = {this.logout}
firstName={this.state.client.firstName}
lastName={this.state.client.lastName}
userId={this.props.userId}
auth = {this.props.auth}
classes={this.props.classes}/>
)
}
}
NavbarC.propTypes = {
auth: PropTypes.bool.isRequired,
firstName: PropTypes.string.isRequired,
lastName: PropTypes.string.isRequired
};
const mapStateToProps = (state) => {
return {
auth: state.AuthR.auth,
firstName: state.AuthR.firstName,
lastName: state.AuthR.lastName,
userId: state.AuthR.userId
};
};
const mapDispatchToProps = dispatch => {
return {
authfn: AuthA(dispatch)
}
};
export default connect(mapStateToProps, mapDispatchToProps) (withStyles(styles)(withRouter(NavbarC)));
If someone have a solution or any questions, I'm here :)
thank you all in advance
First of all, you should avoid componentWillUpdate lifecycle as it's been deprecated.
And for your case, this.getUser(); will be triggered to pull data which then trigger this.setState({client: res.data}). When the app executing this.setState(), your component will be re-render so there's no need to have any other componentLifeCycle.
class NavbarC extends Component {
state = { client:[], userID: null, token: null };
componentDidMount(){
this.setState({
userID: localStorage.getItem("userId"),
token: localStorage.getItem("token")
}, () => {
this.getUser();
})
}
getUser(){
axios.get (`http://localhost:3002/api/clients/${this.state.userID}?access_token=${this.state.token}`)
.then(res => {
this.setState({ client: res.data }, () => {
console.log(this.state)
})
})
}
componentDidUpdate(prevProps, prevState){
if(prevState.userID !== this.state.userID) {
this.getUser();
}
}
logout = () => this.props.authfn.logout();
render() {
return(
<NavbarV
logout = {this.logout}
firstName={this.state.client.firstName}
lastName={this.state.client.lastName}
userId={this.props.userId}
auth = {this.props.auth}
classes={this.props.classes} />
)}
}
I solve it !
This is a solution :
componentDidMount(){
this.setState({
userId: localStorage.getItem("userId"),
token: localStorage.getItem("token")
}, () => {
this.getUser();
})
}
getUser = () => {
axios.get (`http://localhost:3002/api/clients/${this.state.userId}?access_token=${this.state.token}`)
.then(res => {
this.setState({ client: res.data, userId: localStorage.getItem("userId") }, () => {
console.log(this.state)
})
})
}
componentDidUpdate(prevProps, prevState){
if(prevState.userId !== this.props.userId) {
this.setState({ userId: this.props.userId }, () => {
this.getUser();
})
}
}

Resources