API data call not displaying data in React - javascript

Data doesn't seem to be showing in my table for a Axios API call within react believe the error is related to this console error below.
Following a YT tutorial https://www.youtube.com/watch?v=AcYhi08e404
Cannot Read properties of undefined (Reading 'map')]
APP.JS
import React, { useEffect, useState } from 'react';
import { Route, Routes } from 'react-router-dom';
import Navbar from './components/Navbar';
import { ThemeProvider } from './context/ThemeContext';
import Home from './pages/Home';
import Signin from './pages/Signin';
import Signup from './pages/Signup';
import Account from './pages/Account';
import axios from 'axios';
function App() {
const [coins, setCoins] = useState([]);
useEffect(() => {
axios.get(
'https://api.coingecko.com/api/v3/coins/markets?vs_currency=gbp&order=market_cap_desc&per_page=10&page=1&sparkline=true'
)
.then(res => {
setCoins(res.data);
console.log(res.data);
})
.catch(error => console.log(error));
}, []);
return <ThemeProvider>
<Navbar />
<Routes>
<Route path='/' element={<Home coins={coins} />} />
<Route path='/signin' element={<Signin />} />
<Route path='/signup' element={<Signup />} />
<Route path='/account' element={<Account />} />
</Routes>
</ThemeProvider>;
}
export default App;
COINSEARCH.JSX
import React from 'react';
import CoinItem from './CoinItem';
const CoinSearch = ({ coins }) => {
return (
<div>
<div>
<h1>Search</h1>
<form>
<input type="text" placeholder='Search'/>
</form>
</div>
<table className='w-full border-collapse text-center'>
<thead>
<tr className='border-b'>
<th></th>
<th className='px-4'>#</th>
<th className='text-left'>Coin</th>
<th></th>
<th>Price</th>
<th>24h</th>
<th className='hidden md:table-cell'>24h Volume</th>
<th className='hidden sm:table-cell'>Mkt</th>
<th>Last 7 Days</th>
</tr>
</thead>
<tbody>
<tr>
{coins.map((coin) => (
<CoinItem key={coin.id} coin={coin} />
))}
</tr>
</tbody>
</table>
</div>
);
};
export default CoinSearch;
COINITEM.JSX
import React from 'react'
import { AiOutlineStar } from 'react-icons/ai'
import { Sparklines, SparklinesLines } from 'react-sparklines';
export const CoinItem = ({coin}) => {
return (
<tr>
<td>
<AiOutlineStar />
</td>
<td>{coin.market_cap_rank}</td>
<td>
<div>
<img src={coin.image} alt={coin.id} />
<p>{coin.name}</p>
</div>
</td>
<td>{coin.symbol}</td>
<td>{coin.current_price}</td>
<td>{coin.price_change_percentage_24h}</td>
<td>{coin.total_volume}</td>
<td>{coin.market_cap}</td>
<td>
<Sparklines data={coin.sparkline_in_7d.price}>
<SparklinesLines color='green' />
</Sparklines>
</td>
</tr>
);
};
export default CoinItem;
Reasonably new to react and struggling to get past this hurdle, any help would be appreciated!

In Initial render, coin is undefined until it fetches the data , so use shortcircuit condition in COIN component
<tbody>
<tr>
// map through coins only if its defined..
{coins && coins.map((coin) => (
<CoinItem key={coin.id} coin={coin} />
))}
</tr>
</tbody>

you are sending props to your home component in App.js can you show me your home component

The problem is data is not reaching CoinSearch component because in home component you are not getting props. your code for home component will be this.
import React from 'react'
import CoinSearch from '../components/CoinSearch'
export const Home = ({coins}) => {
return (
<div>
<CoinSearch coins = {coins} />
</div>
)
}
export default Home;
try this piece of code in home component hopefully it will work.

Related

How to route to another react component using button in react-router-dom v6 [duplicate]

This question already has an answer here:
Problem in redirecting programmatically to a route in react router v6
(1 answer)
Closed last year.
I'm completely new to react and got stuck on the following 'route' part.
Here is the code:
This is my ListEmployeeComponent :
import React, { Component } from 'react';
import EmployeeService from '../services/EmployeeService';
class ListEmployeesComponent extends Component {
constructor(props) {
super(props);
this.state = {
employees: []
}
this.addEmployee = this.addEmployee.bind(this);
}
componentDidMount() {
EmployeeService.getEmployees().then((res) => {
this.setState({employees: res.data});
});
}
addEmployee() {
this.props.history.push('add-employee');
}
render() {
return (
<div>
<h2 className="text-center">Employee List</h2>
<div className="row">
<button className="btn btn-primary" onClick={this.addEmployee}>Add Employee</button>
</div>
<div className="row">
<table className="table table-striped table-bordered">
<thead>
<tr>
<th>Id</th>
<th>First Name</th>
<th>Last Name</th>
<th>Email Id</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
{
this.state.employees.map(
employee =>
<tr key={employee.id}>
<td>{employee.id}</td>
<td>{employee.firstName}</td>
<td>{employee.lastName}</td>
<td>{employee.email}</td>
</tr>
)
}
</tbody>
</table>
</div>
</div>
);
}
}
export default ListEmployeesComponent;
And this is my App.js :
import './App.css';
import {BrowserRouter as Router, Route, Routes} from 'react-router-dom'
import FooterComponent from './components/FooterComponent';
import HeaderComponent from './components/HeaderComponent';
import ListEmployeesComponent from './components/ListEmployeesComponent';
import CreateEmployeeComponent from './components/CreateEmployeeComponent';
function App() {
return (
<div>
<Router>
<HeaderComponent/>
<div className="container">
<Routes>
<Route path="/" element={<ListEmployeesComponent/>}></Route>
<Route path="/home" element={<ListEmployeesComponent/>}></Route>
<Route path="/add-employee" element={<CreateEmployeeComponent/>}></Route>
</Routes>
</div>
<FooterComponent/>
</Router>
</div>
)
}
export default App;
My issue is that I want to route to CreateEmployeeComponent when the button gets clicked, but there is no action happening when I click the button. I tried checking the new documentation for react-router v6 but it wasn't much help.
What can I do differently here to resolve my issue?
Solution 1:
You can wrap the button in ListEmployeeComponent using Link from react-router-dom.
<Link to="/add-employee">
<button className="btn btn-primary">Add Employee</button>
</Link>
reference: react-router-dom
Solution 2:
history in react-router-dom v6 has been replaced by Navigate. So if you want to push /add-employee to history you need to use
<Navigate to='/add-employee' push={true}/>
Make following changes in your ListEmployeeComponent.js :
add a state in your constructor:
constructor(props) {
super(props);
this.state = {
navigate: false,
employees: []
}
this.addEmployee = this.addEmployee.bind(this);
}
change your function:
addEmployee() {
this.props.history.push('add-employee');
}
to
addEmployee() {
this.setState({
navigate: true,
});
}
and change your render method to:
render() {
const { navigate } = this.state;
if (navigate) {
return <Navigate to="/add-employee" push={true} />;
}
return (
<div>
<h2 className="text-center">Employee List</h2>
<div className="row">
........
//rest of the code
}
reference: react-router-dom-v6 doc
First you have to import link in ListEmployeeComponent
and
have to use button tags between link tags
and you have to add [to="/add-employee"] attributes to link tag
import {Link} from "react-router-dom";
<Link to="/add-employee">
<button
className="btn btn-primary"
onClick={this.addEmployee}
>
Add Employee
</button>
</Link>

Database API search and show result in List (React Native)

export class Diet extends Component {
render() {
return (
<SearchBar/>
<List>
<TouchableOpacity>
<Text>Foods</Text>
</TouchableOpacity>
</List>
)}}
Hey everyone, I can't figure out the following: I am trying to search foods from the database Edamam API by the SearchBar and list them in the List, this is the link of the page: https://developer.edamam.com/food-database-api-docs how can I do this?
Using Axios you can use your API url and using the state you can store the data and use it.
import React, {Component} from 'react';
import {Button, Card, CardBody, Col, Input, Modal, ModalBody, ModalFooter, ModalHeader, Row, Table} from "reactstrap";
import axios from 'axios';
import {FormGroup} from "react-bootstrap";
import InputColor from "react-input-color";
class labelx extends Component {
state = {
labels: []
}
componentWillMount() {
axios.get('http://APIURL').then(response => {
this.setState({
labels: response.data.data
})
}).then(console.log(this.state))
;
}
render() {
let projects = this.state.labels.map((book) => {
return (
<tr key={book.id}>
<td>{book.name}
</td>
<td style={{backgroundColor: book.color}}>{book.color}</td>
<td>
<Button color="danger" onClick={this.deleteProperty.bind(this, book.id)}>Delete</Button>
</td>
</tr>
)
});
return (
<>
<div className="content">
<Row>
<Col md="12">
<Card>
<CardBody>
<div className="content">
<div className="card-header">
<Table>
<thead>
<tr>
<th>name</th>
<th>color</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
{projects}
</tbody>
</Table>
</div>
</div>
</CardBody>
</Card>
</Col>
</Row>
</div>
</>
);
}
}
export default labelx;

React Component Not Rendering the content

React router not rendering my JSX. The initial page renders the content inside. When I click add employee it doesn't display the content of the components. It renders a blank page. I'm a beginner in React.
CreateEmployeeComponent.jsx renders a blank page.
Below is the code of each file. Thanks in advance
App.js
import './App.css';
import React from 'react';
import ListEmployeeComponent from './components/ListEmployeeComponent';
import CreateEmployeeComponent from './components/CreateEmployeeComponent';
import HeaderComponent from './components/HeaderComponent';
import FooterComponent from './components/FooterComponent';
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom'
function App() {
return (
<div>
<Router>
<div>
<HeaderComponent />
<div className="container">
<Switch>
<Route path="/" exact component={ListEmployeeComponent}></Route>
<Route path="/employees" component={ListEmployeeComponent}></Route>
<Route path="/add-emplyee" component={CreateEmployeeComponent}></Route>
</Switch>
</div>
<FooterComponent />
</div>
</Router>
</div>
);
}
export default App;
ListEmployeeComponent
import React, { Component } from 'react';
import EmployeeService from '../services/EmployeeService';
class ListEmployeeComponent extends Component {
constructor(props) {
super(props)
this.state = {
employees: []
}
this.addEmployee = this.addEmployee.bind(this);
}
componentDidMount() {
EmployeeService.getEmployees().then((res) => {
this.setState({ employees: res.data });
})
}
addEmployee() {
this.props.history.push('/add-employee');
}
render() {
return (
<div>
<h2 className="text-center">Employees List</h2>
<div className="row">
<button className="btn btn-primary" onClick={this.addEmployee}>Add Employee</button>
</div>
<div className="row">
<table className="table table-striped table-bordered">
<thead>
<tr>
<th>Employee First Name</th>
<th>Employee Last Name</th>
<th>Employee Email Id</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
{
this.state.employees.map(
employee =>
<tr key={employee.id}>
<td> {employee.firstName} </td>
<td> {employee.lastName} </td>
<td> {employee.emailId} </td>
</tr>
)
}
</tbody>
</table>
</div>
</div>
);
}
}
export default ListEmployeeComponent;
CreateEmployeeComponent
import React, { Component } from 'react';
class CreateEmployeeComponent extends Component {
render() {
return (
<div>
<h1>Create Employee...</h1>
</div>
);
}
}
export default CreateEmployeeComponent;
You got type mistake : /add-emplyee -> /add-employee.
<Route path="/add-emplyee" component={CreateEmployeeComponent}></Route>
Please check it first

Getting “Cannot call a class as a function” in my React Project

I am trying to connect my react app to firebase, it was working perfectly befor connecting it to firebase, now I am getting this error:
Clients
src/components/clients/Clients.js:16:8
if (clients) {
return (
<div>
<div className="row">
<div className="col-md-6">
<h2>
here is my Clients.js code :
import React, { Component } from "react";
import { Link } from "react-router-dom";
import { compose } from "redux";
import { connect } from "react-redux";
import { firestoreConnect } from "react-redux-firebase";
import PropTypes from "prop-types";
class Clients extends Component {
render() {
const clients = this.props.clients;
if (clients) {
return (
<div>
<div className="row">
<div className="col-md-6">
<h2>
{" "}
<i className="fas fa-users" /> Clients{" "}
</h2>
</div>
<div className="col-md-6">---</div>
</div>
<table className="table table-striped">
<thead className="thead-inverse">
<tr>
<th>Name</th>
<th>Email</th>
<th>Balance</th>
<th />
</tr>
</thead>
<tbody>
{clients.map(client => (
<tr key={client.id}>
<td>
{client.firstName} {client.lastName}
</td>
<td>{client.email}</td>
<td>${parseFloat(client.balance).toFixed(2)}</td>
<td>
<Link
to={`/client/${client.id}`}
className="btn btn-secondary btn-sm"
>
<i className="fas fa-arrow-circle-right" /> Details
</Link>
</td>
</tr>
))}
</tbody>
</table>
</div>
);
} else {
return <h1>Loading</h1>;
}
}
}
Clients.prototype = {
firestore: PropTypes.object.isRequired,
clients: PropTypes.array
};
export default compose(
firestoreConnect([{ collection: "clients" }]),
connect((state, props) => ({
clients: state.firestore.ordered.clients
}))
)(Clients);
How can i solve that problem ? it's first time for me to try fire base.
I am using "react-redux" version 5.1.1 and "react-redux-firebase" version 2.2.4.
You seems to use react-router.
In your router .js file, change this:
<Route path="/" render={Clients} />
To this:
<Route path="/" component={Clients} />
Another fix would be to sadly avoid "compose" by doing this:
connect(
(state, props) => ({
clients: state.firestore.ordered.clients
})
)(
firestoreConnect([{ collection: "clients" }])(Clients)
);
I've fixed the problem by changing these lines :
First I changed:
const clients = this.props.clients;
To :
const { clients } = this.props;
Then I changed :
Clients.prototype = {
firestore: PropTypes.object.isRequired,
clients: PropTypes.array
};
To :
Clients.propTypes = {
firestore: PropTypes.object.isRequired,
clients: PropTypes.array
};
and now it is working perfectly

How to render a component in a different page when click on a link in a table row in ReactJs

I'm a beginner in ReactJs, and I have a ProjectsList component which includes an html table. One of its columns is a link which when clicked it must navigate to a different page rendering a ProjectInfo component.
But, what happens is that the component is rendered in the same page of ProjectsList component at the end of the table.
ProjectsList component is rendered when clicked on a link Show Projects in Projects component.
Projects.component.jsx
import React, { Component } from "react";
import { Link, Route, Switch } from "react-router-dom";
import NewProject from "../NewProject/NewProject.component";
import ProjectsList from "../ProjectsList/ProjectsList.component";
import "./Projects.css";
export default class Projects extends Component {
render() {
return (
<div className="projects-dashboard">
<nav className="nav-up">
<ul>
<li>
<Link to={"/dashboard/projects/add"}>add project</Link>
</li>
<li>
<Link to={"/dashboard/projects/list"}>show projects</Link>
</li>
</ul>
</nav>
<main>
<Route path={"/dashboard/projects/add"} component={NewProject} />
<Route path={"/dashboard/projects/list"} component={ProjectsList} />
</main>
</div>
);
}
}
ProjectsList.component.jsx
import React, { Component } from "react";
import axios from "axios";
import { Route, Link } from "react-router-dom";
import "./ProjectsList.css";
import ProjectInfo from "../ProjectInfo/ProjectInfo.component";
export default class ProjectsList extends Component {
constructor(props) {
super(props);
this.state = {
allProject: []
}
}
componentWillMount() {
this.fetchAllProjects();
}
componentDidMount() {
document.body.style.overflowY = "auto";
}
fetchAllProjects = () => {
axios.get("/api/projects").then(res => {
this.setState({ allProject: res.data }, () => { console.log(this.state.allProject); });
});
};
render() {
const projects = this.state.allProject.map(project => {
return (
<tr>
<td>{project.id}</td>
<td>{project.title}</td>
<td>{project.organization_name}</td>
<td className="project-options">
<Link to={`/dashboard/projects/list/${project.id}`}>
<i className="far fa-eye" /> show
</Link>
</td>
</tr>
);
});
return (
<div>
<table class="projects-list-table">
<thead>
<tr>
<th>
<h1>Project ID</h1>
</th>
<th>
<h1>Project Name</h1>
</th>
<th>
<h1>Organization Name</h1>
</th>
<th>
<h1>Options</h1>
</th>
</tr>
</thead>
<tbody>{projects}</tbody>
</table>
<main>
<Route path={"/dashboard/projects/list/:id"} component={ProjectInfo} />
</main>
</div>
);
}
}
ProjectInfo.component.jsx
import React, { Component } from 'react';
import "./ProjectInfo.css";
export default class ProjectInfo extends Component {
render() {
return (
<div>
<h1>Project Info Component</h1>
</div>
)
}
}
React router includes those components to the specified section where the Route tag is. For instance:
<section>
<h1>Hello</h1>
<Route path={"/random/path"} component={MyComponent} />
</section>
will return
<section>
<h1>Hello</h1>
<MyComponent />
</section>
to get around this you need to add it to the same level of routing as your PrjectList route.
so change this
<main>
<Route path={"/dashboard/projects/add"} component={NewProject} />
<Route path={"/dashboard/projects/list"} component={ProjectsList} />
</main>
to
<main>
<Route path={"/dashboard/projects/add"} component={NewProject} />
<Route exact path={"/dashboard/projects/list"} component={ProjectsList} />
<Route exact path={"/dashboard/projects/list/:id"} component={ProjectInfo} />
</main>
EDIT
The last route should not have the exact tag on
<main>
<Route path={"/dashboard/projects/add"} component={NewProject} />
<Route exact path={"/dashboard/projects/list"} component={ProjectsList} />
<Route path={"/dashboard/projects/list/:id"} component={ProjectInfo} />
</main>
If you want to exclusively render a component, meaning that you want to only render one specific component (which in you case is ProjectInfo) when you click on the link in the table, and in this case you don't want to render the Projects component, you need to use Switch within the router.
From the official docs
<Switch>
Renders the first child <Route> or <Redirect> that
matches the location.
How is this different than just using a bunch of <Route>s?
<Switch> is unique in that it renders a route exclusively. In
contrast, every <Route> that matches the location renders
inclusively.
Consider this code:
<Route path="/about" component={About}/>
<Route path="/:user" component={User}/>
<Route component={NoMatch}/>
If the URL is /about, then <About>, <User>, and <NoMatch> will all
render because they all match the path. This is by design, allowing us
to compose <Route>s into our apps in many ways, like sidebars and
breadcrumbs, bootstrap tabs, etc.
So, change your Projects component to something like this (You are already importing Switch so no need to import it again):
<main>
<Switch>
<Route exact path={"/dashboard/projects/add"} component={NewProject} />
<Route exact path={"/dashboard/projects/list"} component={ProjectsList} />
</Switch>
</main>

Categories

Resources