I am newbie to reactjs and I would like to ask if it is possible to achieve this.
I have two files, I would like to pass the ID from Home.js to DataModel.js
Heres my code:
DataModel.js
const axios = require('axios');
const base_url = 'https://jsonplaceholder.typicode.com';
function getUSers(id) {
return axios.get(base_url + '/users/' + id)
}
export const getUSers = getUSers(id);
=================================
Home.js
import { getUSers } from './DataModels';
class Home extends Component {
constructor(props){
super(props);
this.state = {
records: ''
}
}
render(){
let id = 2;
getUsers(id); // -----> How to pass this ID?
return (
<div>
//Codes
</div>
);
}
}
Assuming your DataModel.js exists in the same origin src folder as your component. You can minimize your file by using some ES6 JavaScript.
import axios from "axios"
const base_url = 'https://jsonplaceholder.typicode.com';
export const getUsers = (id) => {
return axios.get(base_url + '/users' + id)
}
Then in Home.js you should call that function in componentDidMount() which is the React life-cycle method that is triggered after the component has first rendered (after first displaying the content).
import { getUsers } from './DataModels';
class Home extends Component {
constructor(props){
super(props);
this.state = {
records: ''
}
}
componentDidMount(){
let id = 2
getUsers(id)
.then((res) => {
this.setState({
records: res.data
})
})
}
render(){
return (
<div>
//Codes
</div>
);
}
}
Add your fetch in componentDidMount().
// Data Model
function getUsers(id) {
return axios.get(base_url + '/users' + id) // return a promise
}
export const getUsers; // named-export function
// Component
class Home extends Component {
...
async componentDidMount() {
let id = 2; // for sample use only
const users = await getUsers(id);
console.log(users); // verify if fetched correctly
}
...
}
Do not put any side effects in render() that can alter the state of the component. Say if you store user in state variable.
this.state = {
users: {},
}
async fetch = id => {
const users = await getUsers(id)
this.setState({ users }) // altering state.users
}
render() {
fetch(2) // BAD: should not be inside render.
// This will cause many re-renders if you alter state.users
}
Related
I cannot figure out what I am doing wrong here. I submit a request to the API and an object is returned, but I cannot seem to get the component to render.
//Code
import React, { Component } from "react"
import axios from 'axios';
class Weather extends Component {
constructor(props){
super(props)
this.state = {
posts: [],
};
}
componentDidMount() {
const query = "Paris";
const apiKey = {api key here};
const unit = "metric";
const url = "https://api.openweathermap.org/data/2.5/weather?q=" + query + "&appid=" + apiKey + "&units=" + unit;
axios.get(`${url}`)
.then(response => {
console.log(response);
this.setState({posts: response.data})
})
.catch(error => {
console.log(error);
})
}
render() {
const { posts } = this.state;
return(
<>
{posts.length ? <div>Temperature: {posts.main.temp} Description: {posts.weather[0].description}</div> : null}
</>
);
}
}
export default Weather;
enter image description here
constructor(props) {
super(props);
this.state = {
message: ""
};
}
async getData() {
this.setState({...this.state})
await axios.get("https://g...")
.then(function(response) {
console.log(response);
this.setState({message: response.data})
}).bind(this)
}
render() {
return (
<div>
{this.state.message}
</div>
);
}
I tried to use this code to get data from the API. However, the message that is printed out is only linked to the original constructor, and the getData() function does not change the state. How should I go around changing the state after getting data?
You should use componentDidMount, and put the function requesting data in componentDidMount life circle.
By the way, you can add a loading to enhance the user experience : )
import React from 'react';
import "./styles.css";
const BASE_URL = 'https://api.github.com';
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
message: ''
}
}
componentDidMount() {
this.getData();
}
async getData() {
try {
const result = await fetch(`${BASE_URL}/repos/facebook/react`);
const toJson = await result.json();
const stringify = JSON.stringify(toJson, null, 2);
this.setState({
message: stringify
})
} catch (error) {
// ignore error.
}
}
render() {
const { message } = this.state;
return (
<div>
{message}
</div>
)
}
}
export default App;
If you are using 'async' and 'await' you don;t have to use then() function
you can write
const data = await axios.get("url")
console.log(data.data)
this.setState({message:data.data})
i'm new to React and I need help with passing props to API URL. I have two class components -> (MyClass) works fine. However when I use variable from MyClass as props in other class component (MyOtherClass), it seems to work only in "render" part. I mean <div> variable: {variable}, url : {url2}</div> is shown in app as expected but when I try to pass this variable from props to API URL, it is not working and instead the URL looks like this: "http://localhost:55111/status/[object Object]". Any ideas what might cause the problem??
Here's my code:
import React, { Component } from 'react'
import axios from 'axios'
export default class MyClass extends Component {
constructor(props) {
super(props);
this.state = {
data: {}
}
}
componentDidMount() {
axios
.get("http://localhost:55111/start")
.then(response => {
this.setState({
data: response.data
});
console.log(this.state.data);
})
.catch(err => {
this.err = err;
});
}
render() {
const variable = this.state.data.sent
return (
<div>
<h1>Hello worlds</h1>
<p>var: {variable}</p>
<MyOtherClass variable={variable} />
</div>
);
}
}
This is the other class component causing troubles:
class MyOtherClass extends Component {
constructor(props) {
super(props);
this.state = {
data: {}
};
}
async componentDidMount() {
const {variable} = this.props
axios.get(`http://localhost:55111/status/${variable}`)
.then(response => {
this.setState({
data: response
});
console.log(this.state);
})
render() {
const { variable } = this.props
const url2 = `http://localhost:55111/status/${variable}`
return (
<div>variable: {variable}, url : {url2}</div>
);
}
}
import React, { Component } from 'react'
import axios from 'axios'
export default class MyClass extends Component {
constructor(props) {
super(props);
this.state = {
data: {}
}
}
componentDidMount() {
this.getData()
}
async getData() => {
const response = await axios.get("http://localhost:55111/start")
this.setState({data: response.data})
}
render() {
const variable = this.state.data.sent
return (
<div>
<h1>Hello worlds</h1>
<p>var: {variable}</p>
<MyOtherClass variable={variable} />
</div>
);
}
}
Use the async await.
I have a component that calls api and returns data, url is like this: https://myapi/CLASS_NBR. But right now the api does not get fired and it returns null. I checked the browser network status, there is not api call. Any idea? My code is as below:
import React, { Component } from "react";
import axios from "axios";
class CourseDetail2 extends Component {
state = {
CLASS_NBR: this.props.match.params.CLASS_NBR,
course: null
};
componentDidMount() {
const { CLASS_NBR } = this.state;
this.runSearch();
}
runSearch = async () => {
const response = await axios.get(
`api/${this.props.match.params.CLASS_NBR}`
);
this.setState({ course: response.data });
};
render() {
const course = this.state.course; //null here
return (
<div>
Course Detail: CLASS NBR {this.props.match.params.CLASS_NBR}
////this information is passed in through react-router Link
{course.SUBJECT} //null
CATALOGNO:{course.CATALOG_NBR}//null
</div>
);
}
}
export default CourseDetail2;
I'm working on my first API with React. I am able to console log my current state after its loaded and the state for that array is set. However, running my component with a prop "FragrancesArray" which is set after loading the data from this.state.fragrances returns in not a function.
Using axios async and await.
No idea why? Can someone help?
Thanks.
My code:
// Core React
import React, { Component } from 'react';
// Axios
import axios from 'axios';
// Constants
import { FRAGRANCES_URL, BLOGS_URL, MAKE_UP_URL } from 'constants/import';
// Components
import Fragrances from 'components/Fragrances/Fragrances';
class App extends Component {
state = {
fragrances: [],
blogs: [],
makeup: []
}
getCoffee() {
return new Promise(resolve => {
setTimeout(() => resolve('☕'), 0); // it takes 1 seconds to make coffee
});
}
async showData() {
try {
// Coffee first
const coffee = await this.getCoffee();
console.log(coffee); // ☕
// Axios API's
const fragranceData = axios(FRAGRANCES_URL);
const blogData = axios(BLOGS_URL);
const makeupData = axios(MAKE_UP_URL);
// await all three promises to come back and destructure the result into their own variables
await Promise.all([fragranceData, blogData, makeupData])
.then((data) => {
this.setState({
fragrances: data[0],
blogs: data[1],
makeup: data[2]
});
const { blogs } = this.state;
console.log(blogs);
})
} catch (e) {
console.error(e); // 💩
}
}
componentDidMount() {
this.showData();
}
render() {
return (
<Fragrances FragranceArray={this.state.fragrances} AppURL={FRAGRANCES_URL} />
)
}
}
export default App;
In react, before you can set/use state, you need to declare it with getInitialState() but with ES6 class model you initialize state in a constructor.
class App extends Component {
constructor(props) {
super(props)
//- Initialize default state values
this.state = {
fragrances: [],
blogs: [],
makeup: []
}
}
//The rest of code stays the same.
render() {
return (
<Fragrances FragranceArray={this.state.fragrances} AppURL={FRAGRANCES_URL} />
)
}
}
More about React state