Fetch API data using React - reactjs

I have a react, which uses django rest framework API. I'm to get JSON data but it seems I'm not fetching the information correctly or I'm not rendering in the right way:
import React, { Component } from 'react' ;
class App extends Component {
state = {
todos: []
};
async componentDidMount() {
fetch('http://127.0.0.1:8000/api/todos/')
.then(results =>{
console.log(results)
const get_todos = results.map( c=>{
return {
id: c.id,
title: c.title,
descripttion: c.title
};
});
const newstate = Object.assign({},this.state,{
todos: get_todos
});
this.setState(newstate);
}).catch(error=> console.log(error));
}
render(){
return (
<div className="App">
{this.state.todos}
</div>
)
}
}
export default App;

it should be
state = { loading : true }
componentDidMount() {
fetch('http://127.0.0.1:8000/api/todos/')
.then(blob => blob.json())
.then(response => {
...
})
}

Related

Unable to render data from api into table

Api url: https://dev.dashmed.in/sample-data
my code for fetching api and rendering in a table:
import React, { Component } from 'react'
import axios from 'axios'
export default class javascriptMap extends Component {
constructor(props){
super(props)
this.state = {
data: []
}
}
getData(){
axios.get('https://dev.dashmed.in/sample-data').then(res => {
var data = res.data
this.setState({data : data})
})
}
componentDidMount(){
this.getData()
}
render() {
return (
<>
<ul>
{this.state.data.map(d => (<li key={d.medName}>{d.saltName}</li>))}
</ul>
</>
)
}
}
Please point out where the error is being committed.
Because your res.data contains {status: true, data: Array(5000)}. You need to set res.data.data into state.
getData(){
axios.get('https://dev.dashmed.in/sample-data').then(res => {
const data = res.data.data
this.setState({data : data})
})
}

How can I put the data inside the MuiDataTable with these codes?

This is my code and how can I push the data inside the MuiDataTable of data={data} with my componentDidMount(). I can already fetch the data from my user collection, however, I do not know enough about mui datatable on how to pass it there. This is the one mui datatable -
https://www.material-ui-datatables.com/
import React, {Component} from 'react';
import MUIDataTable from "mui-datatables";
import {firestore} from './../../../firebase/firebase.utils';
const columns = ["Display Name","Email"];
class UserTable extends Component {
state = { user : null}
componentDidMount() {
firestore.collection('users')
.get()
.then( snapshot => {
const users = []
snapshot.forEach(doc => {
const data = doc.data()
users.push(data)
})
this.setState({ users : users})
// console.log(snapshot)
})
.catch(error => console.log(error))
}
render() {
return (
<MUIDataTable
title={"Users"}
columns={columns}
data={data}
// options={options}
/>
);
}
}
export default UserTable;
You need to pass array of object formatted with your column names' as key like {"Display Name": value, Email:other value}.
You need to pass the state into the constructor like:
constructor() {
super();
this.state = { users: [] };
}
And then you just have to pass this.state.usersto MUIDataTable props data, like:
<MUIDataTable
title={"Users"}
columns={this.columns}
data={this.state.users}
// options={options}
/>
For the example I used axios ro fetch data but this work with firestore to:
import MUIDataTable from "mui-datatables";
import { Component } from "react";
import * as axios from "axios";
class UserTable extends Component {
columns = ["Display Name", "Email"];
constructor() {
super();
this.state = { users: [] };
}
componentDidMount() {
axios
.get("/users.json")
.then((res) => {
const userData = res.data.map((u) => {
return {
"Display Name": u.name,
Email: u.email
};
});
console.log(userData);
this.setState({
users: userData
});
})
.catch((error) => console.log(error));
}
render() {
return this.state.users ? (
<MUIDataTable
title={"Users"}
columns={this.columns}
data={this.state.users}
// options={options}
/>
) : (
<div>Loading...</div>
);
}
}
export default UserTable;
With your code this would like :
import MUIDataTable from "mui-datatables";
import { Component } from "react";
import * as axios from "axios";
class UserTable extends Component {
columns = ["Display Name", "Email"];
constructor() {
super();
this.state = { users: [] };
}
componentDidMount() {
firestore.collection('users')
.get()
.then( snapshot => {
const users = []
snapshot.forEach(doc => {
const data = doc.data()
users.push({"Display Name":data.displayName, Email: data.email});
});
return users;})
.then(userList => this.setState({users:userList});
})
.catch(error => console.log(error))
}
render() {
return this.state.users ? (
<MUIDataTable
title={"Users"}
columns={this.columns}
data={this.state.users}
// options={options}
/>
) : (
<div>Loading...</div>
);
}
}
export default UserTable;
UPDATE:
here you can find a working example with firestore

Props not displaying from fetch call

I am trying to display recipes and not sure if I have this setup correctly. I am pulling recipes from a rails api via get fetch request. At the moment nothing is displaying.
Here is my recipe container:
import React, { Component } from 'react'
import RecipeList from '../components/RecipeList'
import RecipeInput from '../components/RecipeInput'
import { connect } from 'react-redux'
import { postRecipes } from '../actions/postRecipes.js'
import { getRecipes } from '../actions/getRecipes'
class RecipeContainer extends Component{
constructor(props){
super(props)
}
componentDidMount(){
getRecipes()
}
render(){
return (
<div>
<RecipeInput postRecipes={this.props.postRecipes} />
<RecipeList getRecipes={this.props.recipes} />
</div>
)
}
}
const mapStateToProps = state =>({
recipes: state.recipes
})
const mapDispatchToProps = dispatch =>{
return{
postRecipes: (recipe) => dispatch(postRecipes(recipe)),
getRecipes: () => dispatch(getRecipes())
// deleteRecipe: id => dispatch({type: 'Delete_Recipe', id})
}
}
export default connect(mapStateToProps,mapDispatchToProps)(RecipeContainer)
Here is my get request....notice that I am returning my Recipe component here.
export const getRecipes = () => {
const BASE_URL = `http://localhost:10524`
const RECIPES_URL =`${BASE_URL}/recipes`
return (dispatch) => {
dispatch({ type: 'START_FETCHING_RECIPES_REQUEST' });
fetch(RECIPES_URL)
.then(response =>{ return response.json()})
.then(recipes => dispatch({ type: 'Get_Recipes', recipes }));
};
}
This is where I am trying to render the Recipe component from the get request
import React, {Component} from 'react';
// import { getRecipes } from '../actions/getRecipes.js';
import Recipe from './Recipe.js'
class RecipeList extends Component {
// componentDidMount(){
// getRecipes()
// }
render() {
return (
<div>
{this.props.recipes.map(recipe => (<Recipe recipe={recipe} key={recipe.id} />))}
</div>
)
}
}
export default RecipeList;
Edit: Added reducer
switch(action.type){
case 'Add_Recipe':
const recipe = {
name: action.name,
ingredients: action.ingredients,
chef_name: action.chef_name,
origin: action.origin,
category: action.category
}
return{
...state,
recipes: [...state.recipes, recipe],
}
case 'START_FETCHING_RECIPES_REQUEST':
return {
...state,
recipes: [...state.recipes],
requesting: true
}
case 'Get_Recipes':
return {
...state, recipes: action.recipes,
requesting: false
}
default:
return state
}
}
How can I correct this to make it work?
Issue
You are not passing the recipes to the RecipeList component that were fetched and presumably stored in state, and fed back to the UI via RecipeContainer.
Solution
Pass the recipe state from RecipeContainer to RecipeList as a prop. and then render/map the recipes from props.
RecipeContainer
class RecipeContainer extends Component{
componentDidMount() {
getRecipes();
}
render() {
return (
<div>
<RecipeInput postRecipes={this.props.postRecipes} />
<RecipeList getRecipes={this.props.recipes} /> // <-- pass recipe state
</div>
)
}
}
const mapStateToProps = state => ({
recipes: state.recipes,
});
const mapDispatchToProps = dispatch => {
return {
postRecipes: (recipe) => dispatch(postRecipes(recipe)),
getRecipes: () => dispatch(getRecipes())
}
};
RecipeList
class RecipeList extends Component {
render() {
const { recipes } = this.props;
return (
<div>
{recipes.map(recipe => (
<Recipe recipe={recipe} key={recipe.id} />
))}
</div>
);
}
}
The actual solution to this was I needed to have an explicit return in my mapStateToProp function.
Eg.
const mapStateToProp = state =>{
return {
recipes: state.recipes
}
}

React HOC with Router not finding page

Hi I am working on a react app with Routing and HOC. I expect to see a page but i get page not found when i know the page is there.
in componentDidMount this.setState, data is shown as undefined but in the HOC wrapper i see the data arrive from the server.
Before I wrapped the page in HOC i could see it rendering content so I know the content exists.
Here is my Page component which is being called via a Route :
import React, { Component } from "react";
import WithBackend from "./WithBackend";
class Page extends Component {
constructor(props) {
super(props);
this.state = { model: null };
}
render() {
if (this.state.model != null) {
return (
<div className="container">
<div className="row">
<div className="col-md">
<h1>{this.state.model.title}</h1>
</div>
</div>
</div>
);
} else {
return (
<div>
<h2>Home</h2>
</div>
);
}
}
componentDidMount() {
const data = this.props.getPage("1");
console.log(data);
this.setState({
model: data,
});
}
}
export default WithBackend(Page);
Here is the HOC component WithBackend: I am not sure if i should be setting the state on this class on in the class that is being wrapped.
When i debug the code in the getPage method, in the setState part i see the data being populated from the backend server.
import React from "react";
import ContentService from "./ContentService";
const WithBackend = (WrappedComponent) => {
class HOC extends React.Component {
constructor() {
super();
this.contentService = new ContentService();
this.getPage = this.getPage.bind(this); // <-- Add this
}
getPage(id) {
this.contentService
.getPage(id)
.then((response) => response.json())
.then((data) => {
this.setState({ model: data });
})
.catch((e) => {
console.log(e);
});
}
render() {
return <WrappedComponent getPage={this.getPage} {...this.props} />;
}
}
return HOC;
};
export default WithBackend;
and here is the contentService which only returns a promise:
class ContentService {
pageUrl = process.env.REACT_APP_BASE_URL + "/pages/";
getPage(id) {
const path = this.pageUrl + id;
const fetchPromise = fetch(path, {
method: "GET",
});
return Promise.resolve(fetchPromise);
}
}
export default ContentService;
Could anyone please advice what i am doing wrong?
Thanks in advance.
getPage is an asynchronous method, that should return a promise:
getPage(id) {
return this.contentService
.getPage(id)
.then((response) => response.json())
.catch((e) => {
console.log(e);
});
}
And then
componentDidMount() {
this.props.getPage("1").then(model => this.setState({ model }));
}

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

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.

Resources