React : Displaying search results not working - javascript

I'm learning React and I'm creating a little application of patient management. The project backend was coded in Laravel and working, now remains the frontend with React.
The display of the patients in a table using Axios is completely fine, but when I try to search, it seems to not work. The search code was pasted directly from a solution I stumbled on here with little adjustments.
For clarification, the API of the search when typed manually in the browser is working fine, so I have a problem with React.
How can I manage to search my table in React using my search API ?
Component JS:
import React, { Component } from "react";
import axios from "axios";
import { Link } from "react-router-dom";
import { Container, Dropdown, ListGroup, Button } from "react-bootstrap";
import { Table, Thead, Tbody, Tr, Th, Td } from "react-super-responsive-table";
import "./styles.css";
class Patient extends React.Component {
constructor(props) {
super(props);
this.state = {
patients: [],
};
}
//Pasted from a solution
const[patient,SearchData]=useState([]);
//End pasted
componentDidMount() {
axios
.get("api/patients")
.then((response) => {
this.setState({ patients: response.data });
})
.catch((err) => console.log(err));
// Pasted from a solution + This code seems to not work but the API is working
const Search=(key)=>{
console.log(key);
fetch("api/patients/search?q="+key)
.then((data)=>{
data.json().then((resp)=>{
console.warn("resp:",resp)
SearchData(resp)
})
})
}
//End pasted
}
render() {
return (
<div>
<Container>
<div className="col-md-4 my-2 my-md-0">
<div className="input-icon">
<input
type="text"
className="form-control"
placeholder="Search..."
onChange={(event) => Search(event.target.value)}
/>
<span>
<i className="flaticon2-search-1 text-muted" />
</span>
</div>
</div>
<Table className="table table-hover">
<Thead className="thead-light text-center">
<Tr>
<Th>ID</Th>
<Th>FIRST NAME</Th>
<Th>LAST NAME</Th>
</Tr>
</Thead>
<Tbody className="text-center">
{this.state.patients.reverse().map((patient) => (
<Tr>
<Td>
{patient.id}
</Td>
<Td>
{patient.firstname}
</Td>
<Td>
{patient.lastname}
</Td>
</Tr>
))}
</Tbody>
</Table>
</Container>
</div>
);
}
}
export default Patient;

It looks like you're defining Search inside ComponentDidMount, which will drop out of scope before the component renders. Try defining it as part of the component, instead.
You may also need to refer to it as this.Search inside the render block.

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>

Infinite scroll render in ReactJS with React-List using table takes too long

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.

Not able to manipulate map functions in react JS

I am trying to hit an api available at covid19 api [ you can see directly , click it ] but I am not able to map through the state.
I tried browsing the questions and still didn't find it .
my code in app.js is
import React, { Component } from 'react'
import api from '../api/covidapi'
import SearchBar from './SearchBar'
class App extends Component {
constructor(props) {
super(props);
this.state = {
country : 'Please Enter the country',
active_cases : 'No country found',
countries : [],
errorMessage : '',
isLoading : false,
};
}
async componentDidMount() {
const response = await api.get('/summary');
console.log('data loaded = > ', response);
console.log(response.data.Countries.length) // giving 247
console.log('countries ', response.data.Countries) //lists all countries {....},{...}...
this.setState({countries:response.data.Countries})
// console.log('global end')
this.setState({
totalConfirmed : response.data.Global.TotalConfirmed,
})
} //component did mount ended.
onSearchSubmit = async (country) =>{
console.log(country)
try {
const response =
await api.get(`/live/country/${country}/status/confirmed`)
this.setState({country:country, active_cases:response.data[6].Active})
}
catch(e) {
this.setState({errorMessage : "Country Doesn't exist or misspelled"})
}
}; //onsearch submit ended.
render() {
return (
<div>
<div className="container">
<p style={{textAlign:'center',
backgroundColor:'green',
color:'white',
width:'97%',margin:'auto',
padding:'24px',
marginTop:'12px',}}>
Total confirmed as of now is <span> : </span>
<span style={{color : 'red'}} >
{this.state.totalConfirmed}
</span>
</p>
<SearchBar onSubmit = {this.onSearchSubmit}/>
</div>
<div className="container">
<h2 className="bg bg-primary" style={{marginBottom:'0px',
textAlign:'center',marginTop:'15px',
padding:'10px'}}>Covid19 Cases In single Country
</h2>
<table className="table table-striped">
<thead>
<tr>
<th>Country</th>
<th>Acitve Cases</th>
</tr>
</thead>
<tbody>
<tr>
<td>{this.state.country}</td>
<td>{ this.state.active_cases}</td>
</tr>
</tbody>
</table>
</div>
<br />
<hr />
<div className="container">
<div style={{textAlign:'center',color:'red',fontWeight:'bold'}}>
</div>
<h2 className="bg bg-primary" style={{marginBottom:'0px',
textAlign:'center', padding:'10px'}}>
Covid19 Cases Worldwide
</h2>
<table className="table table-striped table-hover table-dark">
<thead>
<tr>
<th>S.N</th>
<th>Country Name</th>
<th>Confirmed Cases</th>
<th> Total Deaths</th>
<th>Total Recovered</th>
</tr>
</thead>
<tbody>
{
Object.keys(this.state.countries).map((country) => (
<tr>
<td>{country}</td>
<td>........</td>
<td>........</td>
<td> ........</td>
<td>............</td>
</tr>
))
}
</tbody>
</table>
</div>
</div>
);
}
}
export default App;
and covidapi.js code is
import axios from 'axios'
export default axios.create({
baseURL :'https://api.covid19api.com'
})
The problem is in this section of the code in app.js
{
Object.keys(this.state.countries).map((country) => (
<tr>
<td>{country}</td>
<td>........</td>
<td>........</td>
<td> ........</td>
<td>............</td>
</tr>
))
}
I am not able to map through countries in my state , I think there is
problem with the Objects and array.
when Render the country that is passed in map it return the integer value like 1,2,3 .... and not able to get other values.
Response in the console looks like this
What I am trying is to display the all the countries list to the table whenever the application loads.
You can use this.state.countries directly without Object.keys() (It is an array already), and use the properties inside each item as follows:
{
this.state.contries.map(item => {
return(
<tr>
<td> { item.Country } </td>
<td> { item.totalConfirmed } </td>
... // Other tds
</tr>
)
}
}

Table row cannot appear as a child of a div component

I am trying to do mapping in render method using Table but it gives error. When I run this component it do not show any output. I share my code below, please have a look in render method where i define table.
Thank you
import React from "react";
import DisplayCRMUser from "./DisplayCRMUser";
export default class App extends React.Component {
constructor(props, context) {
super(props, context);
this.state = { contactReport_entities : []};
}
render() {
return (
<div>
<div className="table-responsive-xs cstm-configure-Content">
<table>
<thead>
<tr>
<th>Type</th>
<th>Topic</th>
<th></th>
</tr>
</thead>
<tbody>
{this.state.contactReport_entities.map ((val, index) => {
<tr key={index}>
<td>{val.subject}</td>
<td>{val.createdon}</td>
</tr>
})}
</tbody>
</table>
</div>
</div>
);
}
}

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

Categories

Resources