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.
I want to render large lists of data inside a table. I am using the React-List library found online, but when the user scrolls about 200 items, the rest of them take too much time to load.
I achieved something like this:
After about 200 items, I get these warnings in the console, and the list starts to render slower and slower like in the image below:
I use React-List for rendering this table and a get request to get all the data once, code will be shown below.
import React from 'react';
import axios from 'axios';
import { toastr } from '../../../components/toastr/toastr.component';
import { Table } from 'react-bootstrap';
import { FontAwesomeIcon } from '#fortawesome/react-fontawesome';
import { faTrashAlt } from '#fortawesome/free-solid-svg-icons';
import DaysJS from 'react-dayjs';
import Loading from '../../../components/loading/loading.component';
import Tooltip from '../../../components/tooltip/tooltip.component';
import ReactList from 'react-list';
import './error.styles.scss';
class ErrorPage extends React.Component {
constructor() {
super();
this.state = {
pending: true,
errors: []
}
};
componentDidMount() {
axios.get('/api/logError').then(resp => {
this.setState({ pending: false, errors: resp.data });
}).catch(() => toastr('error', 'Eroare la preluarea datelor!'));
};
renderItem = (index, key) => {
return (
<tr key={key}>
<td>
{this.state.errors[index].id}
</td>
</tr>
)
};
renderTable (items, ref) {
return (
<div style={{maxHeight: '400px', overflowY: 'scroll'}}>
<Table bordered striped hover size="sm">
<tbody ref={ref}>
{items}
</tbody>
</Table>
</div>
);
}
renderRow = (index, key) => {
const entry = this.state.errors[index]
return (
<tr key={key}>
<td width='40px' className='text-center'>{index}</td>
<td width='40px' className='text-center'>{entry.id_user}</td>
<td width='200px'>{entry.email}</td>
<td width='200px'>{entry.name}</td>
<td width='200px'>{entry.action}</td>
<td>{entry.error}</td>
<td width='120px' className='text-center'><DaysJS format='DD.MM.YYYY - HH:MM'>{entry.createdAt}</DaysJS></td>
<td width='30px' className='cursor-pointer text-center' data-tip data-for='tooltip'>
<Tooltip id='tooltip' message='Șterge eroare'/>
<FontAwesomeIcon className='text-danger' icon={faTrashAlt} />
</td>
</tr>
);
}
render() {
const { pending, errors } = this.state;
return (
<div className='error-page mt-3 row'>
<Loading pending={pending} />
<div className='col-sm-4 fw-bold'>Total erori: {errors.length}</div>
<div className='col-sm-4'>
<h4 className='text-center'>Erori</h4>
</div>
<div className='col-sm-4 text-end'>
<button className='btn btn-danger btn-sm'>
<FontAwesomeIcon icon={faTrashAlt} className='me-1' />
Șterge toate
</button>
</div>
<div className='col-sm-12'>
<Table bordered size="sm">
<thead>
<tr>
<th width='40px'>Id user</th>
<th width='200px'>Email</th>
<th width='200px'>Unitate</th>
<th width='200px'>Acțiune</th>
<th>Eroare</th>
<th width='120px'>Data</th>
<th width='38px'></th>
</tr>
</thead>
</Table>
<ReactList
itemsRenderer={(items, ref) => this.renderTable(items, ref)}
itemRenderer={this.renderRow}
length={errors.length}
/>
</div>
</div>
);
};
};
export default ErrorPage;
I used in AngularJS a library called ng-infinite-scroll that rendered the items with no problem with infinite scroll and I tried to find something similar for ReactJS.
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
Its possible to use a function from the parent component in a child component even if this function changes the parent state? (this function has a parameter)
How would i export it to my child component and use it?
This is the function i want to export and use in my child component:
function atualizarCadastros(novoCadastro){
setCadastros(cadastrosAtuais => {
return[...cadastrosAtuais, novoCadastro]
})
}
Parent component:
import './App.css';
import React, {useState} from 'react';
import {Table, Jumbotron, Button} from 'react-bootstrap'
import Formulario from './Formulario'
import renderCadastros from './renderCadastros'
function App() {
const [Cadastros, setCadastros] = useState([{
"id": 1,
"nome": "Francisca Julia da Costa",
"cpf": "457.696.936-65",
"rg": "47.360.897-2",
"data_nasc": "23/03/1944",
"sexo": "Feminino"
},
{
"id": 2,
"nome": "Noah Felipe Silva",
"cpf": "956.531.431-70",
"rg": "40.974.782-8",
"data_nasc": "11/07/1964",
"sexo": "Masculino"
},
{
"id": 3,
"nome": "Alícia Rosângela Melo",
"cpf": "066.291.353-18",
"rg": "36.214.141-1",
"data_nasc": "18/02/1978",
"sexo": "Feminino"
}])
function atualizarCadastros(novoCadastro){
setCadastros(cadastrosAtuais => {
return[...cadastrosAtuais, novoCadastro]
})
}
return (
<Jumbotron style={{background: 'transparent'}}>
<Formulario/>
<Table striped bordered hover size='sm'>
<thead>
<tr>
<th>id</th>
<th>Nome</th>
<th>CPF</th>
<th>RG</th>
<th>Nascimento</th>
<th>Sexo</th>
<th></th>
</tr>
</thead>
<tbody>
{Cadastros.map(renderCadastros)}
</tbody>
</Table>
</Jumbotron>
);
}
export default App;
Child component:
import './App.css';
import React, {useRef} from 'react';
import {Button, Form, Col} from 'react-bootstrap'
function Formulario (){
return(
<div>
<Form>
<Form.Row>
<Col>
<Form.Label>Identificação</Form.Label>
<Form.Control placeholder="Id" />
</Col>
<Col>
<Form.Label>Nome Completo</Form.Label>
<Form.Control placeholder="João Silva" />
</Col>
<Col>
<Form.Label>CPF</Form.Label>
<Form.Control placeholder="000.000.000-00" />
</Col>
<Col>
<Form.Label>RG</Form.Label>
<Form.Control placeholder="0.000.000" />
</Col>
<Col>
<Form.Label>Data de Nascimento</Form.Label>
<Form.Control placeholder="DD/MM/AAAA" />
</Col>
<Col>
<Form.Label>Sexo</Form.Label>
<Form.Control placeholder="Masculino/Feminino" />
</Col>
</Form.Row>
</Form>
<div style={{display: 'flex', flexDirection: 'column', alignItems: 'center'}}>
<Button style={{margin: '10px'}} variant="primary">Cadastrar</Button>
</div>
</div>
)
}
export default Formulario
Thats other component from the application just so you can see it all:
import './App.css';
import React from 'react';
import {Button} from 'react-bootstrap'
function renderCadastros(cadastro, index){
return(
<tr id={cadastro.id} key={index}>
<td>{cadastro.id}</td>
<td contentEditable="true" suppressContentEditableWarning={true}>{cadastro.nome}</td>
<td contentEditable="true" suppressContentEditableWarning={true}>{cadastro.cpf}</td>
<td contentEditable="true" suppressContentEditableWarning={true}>{cadastro.rg}</td>
<td contentEditable="true" suppressContentEditableWarning={true}>{cadastro.data_nasc}</td>
<td contentEditable="true" suppressContentEditableWarning={true}>{cadastro.sexo}</td>
<td align="center"><Button variant="danger">Excluir</Button></td>
</tr>)
}
export default renderCadastros
You can pass functions down to child components via props, if the function alters state defined in the parent component, when that state has changed it React will re-render the parent and all its children.
import React from "react";
import "./styles.css";
export default function App() {
const [counter, setCounter] = React.useState(1);
const increment = (num) => {
setCounter(prev => prev + num)
}
return (
<div>
<div>Counter: {counter}</div>
<Child increment={increment}/>
</div>
);
}
function Child({increment}) {
handleClick() {
increment(1)
}
return (
<button onClick={handleClick}>Increment counter</button>
)
}
In your parent component you can pass down methods using props.
like this
//set your method to whatever you want to call it in your child component
<Formulario newFunction = {atualizarCadastros} />
then in your child component pass the prop at the top level like this
function Formulario ( {newFunction} ){
return(
<div>
<Form>
<Form.Row>
<Col>
<Form.Label>Identificação</Form.Label>
<Form.Control placeholder="Id" />
</Col>
<Col>
<Form.Label>Nome Completo</Form.Label>
<Form.Control placeholder="João Silva" />
</Col>
<Col>
<Form.Label>CPF</Form.Label>
<Form.Control placeholder="000.000.000-00" />
</Col>
<Col>
<Form.Label>RG</Form.Label>
<Form.Control placeholder="0.000.000" />
</Col>
<Col>
<Form.Label>Data de Nascimento</Form.Label>
<Form.Control placeholder="DD/MM/AAAA" />
</Col>
<Col>
<Form.Label>Sexo</Form.Label>
<Form.Control placeholder="Masculino/Feminino" />
</Col>
</Form.Row>
</Form>
<div style={{display: 'flex', flexDirection: 'column', alignItems: 'center'}}>
<Button style={{margin: '10px'}} variant="primary">Cadastrar</Button>
</div>
</div>
)
}
export default Formulario
so whenever you want to call that function in your child just use newFunction. Hope this makes sense and helps!
You can pass the function as a prop to the child component.
Modify you map function to something like below
{Cadastros.map((item, index) => (
<renderCadastros
cadastro={item}
key={index}
atualizarCadastros={atualizarCadastros} />
)}
And you can consume the data and function in the child component as below
import './App.css';
import React from 'react';
import {Button} from 'react-bootstrap'
function renderCadastros({cadastro, atualizarCadastros}){
return(
<tr id={cadastro.id}>
<td>{cadastro.id}</td>
<td contentEditable="true" suppressContentEditableWarning={true}>{cadastro.nome}</td>
<td contentEditable="true" suppressContentEditableWarning={true}>{cadastro.cpf}</td>
<td contentEditable="true" suppressContentEditableWarning={true}>{cadastro.rg}</td>
<td contentEditable="true" suppressContentEditableWarning={true}>{cadastro.data_nasc}</td>
<td contentEditable="true" suppressContentEditableWarning={true}>{cadastro.sexo}</td>
<td align="center"><Button variant="danger">Excluir</Button></td>
</tr>)
}
export default renderCadastros
import './App.css';
import React, {useState} from 'react';
import {Table, Jumbotron, Button} from 'react-bootstrap'
import Formulario from './Formulario'
import renderCadastros from './renderCadastros'
function App() {
const [Cadastros, setCadastros] = useState([{
"id": 1,
"nome": "Francisca Julia da Costa",
"cpf": "457.696.936-65",
"rg": "47.360.897-2",
"data_nasc": "23/03/1944",
"sexo": "Feminino"
},
{
"id": 2,
"nome": "Noah Felipe Silva",
"cpf": "956.531.431-70",
"rg": "40.974.782-8",
"data_nasc": "11/07/1964",
"sexo": "Masculino"
},
{
"id": 3,
"nome": "Alícia Rosângela Melo",
"cpf": "066.291.353-18",
"rg": "36.214.141-1",
"data_nasc": "18/02/1978",
"sexo": "Feminino"
}])
function atualizarCadastros(novoCadastro){
setCadastros(cadastrosAtuais => {
return[...cadastrosAtuais, novoCadastro]
})
}
return (
<Jumbotron style={{background: 'transparent'}}>
<Formulario/>
<Table striped bordered hover size='sm'>
<thead>
<tr>
<th>id</th>
<th>Nome</th>
<th>CPF</th>
<th>RG</th>
<th>Nascimento</th>
<th>Sexo</th>
<th></th>
</tr>
</thead>
<tbody>
{Cadastros.map((item, index) => (
<renderCadastros cadastro={item} key={index} atualizarCadastros={atualizarCadastros} />
)}
</tbody>
</Table>
</Jumbotron>
);
}
export default App;
You can pass your function through props from the parent to child component. Reference as follows
Parent Component:
replace <Formulario /> with <Formulario atualizarCadastros={() => this. atualizarCadastros}
Arrow function used to bind.
Child Component:
to access the function
function Formulario (props) {
props.atualizarCadastros() // function call anywhere required
}
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