Search data using axios in React using a Laravel API - reactjs

I'm using React and Laravel to make an application. I managed to display data using Axios in a component, and managed to search data separatly in another component using this code :
const [data,setData]=useState([]);
async function search(key)
{
console.warn(key)
let result = await fetch("http://localhost:8000/api/search/"+key);
result = await result.json();
console.warn(result)
setData(result)
}
The problem is that I can't manage to combine between search and displaying data in a single component. How to do so ? I'm using a personal Laravel API.
JS Component of display data ( Without search ):
import React, { Component } from "react";
import axios from "axios";
import { Container, Dropdown, ListGroup, Button } from "react-bootstrap";
import { Table, Thead, Tbody, Tr, Th, Td } from "react-super-responsive-table";
class Patient extends React.Component {
constructor(props) {
super(props);
this.state = {
patients: [],
};
}
componentDidMount() {
axios
.get("api/patients")
.then((response) => {
this.setState({ patients: response.data });
})
.catch((err) => console.log(err));
}
render() {
return (
<div>
<Container>
<div className="form-group">
<label htmlFor="exampleInputEmail1">Search</label>
<input
type="text"
className="form-control"
id=" "
placeholder="Search"
id="name"
/>
</div>
<Table className="table table-hover">
<Thead className="thead-light text-center">
<Tr>
<Th>ID</Th>
<Th>NAME</Th>
<Th>FIRST NAME</Th>
</Tr>
</Thead>
<Tbody className="text-center">
{this.state.patients.reverse().map((patient) => (
<Tr>
<Td>
<b>{patient.id}</b>
</Td>
<Td>
<b>{patient.firstname}</b>
</Td>
<Td>
<b>{patient.lastname}</b>
</Td>
</Tr>
))}
</Tbody>
</Table>
</Container>
);
</div>
);
}
}
export default Patient;
My Laravel Controller to search :
public function search($key)
{
return Patient::where('name','Like',"%$key%")->get();
}
Laravel Route :
Route::get('/search/{key}/', [PatientController::class, 'search']);

Related

Frontend page doesn't display unless i comment out my table making code

Here is my code. I used typescript and my database is in a .json file. My page displays fine when I don't try to display the table and disappears completely
import React, { useState } from "react";
import "./viewAvailableShifts.css";
import "bootstrap/dist/css/bootstrap.min.css";
import MockData from "./data.json";
export class ViewAvailableShifts extends React.Component {
render() {
const [data] = useState(MockData);
return (
<>
<div className="row">
<div className="leftcolumn">
<div className="center">
<h1>Available Shifts</h1>
<div>
<table>
<thead>
<th>First Name</th>
<th>Last Name</th>
</thead>
<tbody>
{data.map((d) => (
<tr key={d.id}>
<td>{d.first_name}</td>
<td>{d.last_name}</td>
<td>{d.email}</td>
<td>{d.gender}</td>
</tr>
))}
</tbody>
</table>
</div>
Have you tried mapping the table rows outside of the return? Also wondering why data was in square brackets? Maybe curley braces or none at all, depending on how you return it from state? so if it's already an array just data if you need to make it an array maybe spread [...data]?
export class ViewAvailableShifts extends React.Component {
render() {
const data = useState(MockData)
const rows = data.map((d) => (
<tr key={d.id}>
<td>{d.first_name}</td>
<td>{d.last_name}</td>
<td>{d.email}</td>
<td>{d.gender}</td>
</tr>
))
return (
<>
<div className="row">
<div className="leftcolumn">
<div className="center">
<h1>Available Shifts</h1>
<div>
<table>
<thead>
<th>First Name</th>
<th>Last Name</th>
</thead>
<tbody>{rows}</tbody>
</table>
</div>
</div>
</div>
</div>
</>
)
}
}
Hooks doesn't work inside class component
import React, { useState } from "react";
import "./viewAvailableShifts.css";
import "bootstrap/dist/css/bootstrap.min.css";
import MockData from "./data.json";
export const ViewAvailableShifts = () => {
const [data] = useState(MockData);
return (
<>
<div className="row">
<div className="leftcolumn">
<div className="center">
<h1>Available Shifts</h1>
<div>
<table>
<thead>
<th>First Name</th>
<th>Last Name</th>
</thead>
<tbody>
{data.map((d) => (
<tr key={d.id}>
<td>{d.first_name}</td>
<td>{d.last_name}</td>
<td>{d.email}</td>
<td>{d.gender}</td>
</tr>
))}
</tbody>
</table>
</div>
What are you trying to accomplish with useState? useState is a hook that listens for changes to data and then changes the UI accordingly. Use state returns two values though, it would be used like this...
const [data, setData]= useState(someDataOrEmptyValueButNeverActuallyEmpty)
onSomeEvent((eventOrDataOrWhatNot) => setData(eventOrDataOrWhatNot))
and then whatever in your UI that was depending on data will adjust to the new values.
So, are you ready?You can't us hooks in class components
export const ViewAvailableShifts = () => {
const [data] = useState(MockData);
‏}
Should be
export default class ViewAvailableShifts extends Component {
constructor() {
super();
this.state: {data: MockData}
}
render(){...}
}

React Datatable Values Duplicating

I'm fetching data from a firebase real-time database and its working, expect the head of the table which is the name, email and stuff. Its supposed to only show up once at the very top like every datatable, instead, its showing on every new entry.
(I apologise everything is in french)
Thanks in advance.
here's a picture:
here's my code:
import React from 'react'
import { bd, auth } from '../firebase'
import "../reserve.css"
import 'bootstrap/dist/css/bootstrap.min.css';
class Pro extends React.Component {
state = {
contacts: null
}
componentDidMount(){
bd.collection('contacts')
.get()
.then( snapshot => {
const contacts = []
snapshot.forEach( doc => {
const data = doc.data()
contacts.push(data)
})
this.setState({ contacts: contacts })
console.log(snapshot)
})
.catch ( error => console.log(error))
}
render(){
return (
<div className="ProClass">
{
this.state.contacts &&
this.state.contacts.map( contact => {
return(
<div className="ProClassReservations">
<table>
<thead>
<tr>
<td>Nom Complet</td>
<td>Email</td>
<td>Date d'arrivée</td>
<td>Date de Départ</td>
<td>Nombre de Personnes</td>
<td>Type de Chambre</td>
<td>Tel</td>
</tr>
</thead>
<tbody>
<tr>
<td>{contact.nom}</td>
<td>{contact.email}</td>
<td>{contact.arrive}</td>
<td>{contact.depart}</td>
<td>{contact.npersonnes}</td>
<td>{contact.type}</td>
<td>{contact.tel}</td>
</tr>
</tbody>
</table>
</div>
)
})
}
</div>
)
}
}
export default Pro
This is because you have the Table headers inside the map, you must ONLY map the values into the respective table rows. All you need to do is append the rows after your headers.
return (
<div className="ProClass">
<div className="ProClassReservations">
<table>
<thead>
<tr>
<td>Nom Complet</td>
<td>Email</td>
<td>Date d'arrivée</td>
<td>Date de Départ</td>
<td>Nombre de Personnes</td>
<td>Type de Chambre</td>
<td>Tel</td>
</tr>
</thead>
<tbody>
{
this.state.contacts &&
this.state.contacts.map( contact => {
return(
<tr>
<td>{contact.nom}</td>
<td>{contact.email}</td>
<td>{contact.arrive}</td>
<td>{contact.depart}</td>
<td>{contact.npersonnes}</td>
<td>{contact.type}</td>
<td>{contact.tel}</td>
</tr>
)
})
}
</tbody>
</table>
</div>
)

No access to "this"

I'm working on a web-application using the MERN stack that displays a table of clients with their name, email, and phone number. I haven't implemented Redux quite yet, but I'm using 'uuid' to supplement data in the table until I can get the redux store set up. So far I have displaying the the list and adding a client to the list working fine, but I am having trouble with the pesky delete button.
This is the current ClientTable component
import React, { Component } from "react";
import { Table, Container, Button } from "reactstrap";
import { connect } from "react-redux";
import {
getClients,
addClient,
editClient,
deleteClient,
} from "../actions/clientActions";
import PropTypes from "prop-types";
const renderClient = (clients, index, id) => {
return (
<tr key={index}>
<td>
<Button
className="remove-btn"
color="danger"
size="sm"
onClick={() => {
this.setState((state) => ({
clients: state.clients.filter((client) => client.id !== id),
}));
}}
>
×
</Button>
</td>
<td>{clients.name}</td>
<td>{clients.email}</td>
<td>{clients.number}</td>
</tr>
);
};
class ClientTable extends Component {
componentDidMount() {
this.props.getClients();
}
onDeleteClick = (id) => {
this.props.deleteClient(id);
};
render() {
const { clients } = this.props.client;
// const { clients } = this.state;
return (
<Container id="listContainer">
<Table
id="listTable"
className="table-striped table-bordered table-hover"
dark
>
<tr class="listRow">
<thead id="tableHeader">
<tr>
<th id="listActions">Actions</th>
<th id="listName">Name</th>
<th id="listEmail">Email</th>
<th id="listNumber">Number</th>
</tr>
</thead>
<tbody class="listRow">{clients.map(renderClient)}</tbody>
</tr>
</Table>
</Container>
);
}
}
ClientTable.propTypes = {
getClients: PropTypes.func.isRequired,
client: PropTypes.object.isRequired,
};
const mapStateToProps = (state) => ({
client: state.client,
});
export default connect(mapStateToProps, {
getClients,
deleteClient,
addClient,
})(ClientTable);
This is the bit of code that is causing me issues
<Button
className="remove-btn"
color="danger"
size="sm"
onClick={() => {
this.setState((state) => ({
clients: state.clients.filter((client) => client.id !== id),
}));
}}
>
×
</Button>
When I click the "delete" button I keep getting TypeError: Cannot read property 'setState' of unedefined
I know the error is because of 'this' isn't bound to anything, but I'm uncertain how to bind it within an onClick event if that is even possible or what even to bind it to. I am just lost as to how to approach this problem. (I'm still quite new to React).
If anyone has any ideas it would be greatly appreciated!
move renderClient function to ClientTable, and use it as a method of this class.
class ClientTable extends Component {
componentDidMount() {
this.props.getClients();
}
renderClient = (clients, index) => {
return (
<tr key={index}>
<td>
<Button
className="remove-btn"
color="danger"
size="sm"
onClick={() => this.onDeleteClient(clients.id)}
>
×
</Button>
</td>
<td>{clients.name}</td>
<td>{clients.email}</td>
<td>{clients.number}</td>
</tr>
);
};
onDeleteClick = (id) => {
this.props.deleteClient(id);
};
render() {
const { clients } = this.props.client;
// const { clients } = this.state;
return (
<Container id="listContainer">
<Table
id="listTable"
className="table-striped table-bordered table-hover"
dark
>
<tr class="listRow">
<thead id="tableHeader">
<tr>
<th id="listActions">Actions</th>
<th id="listName">Name</th>
<th id="listEmail">Email</th>
<th id="listNumber">Number</th>
</tr>
</thead>
<tbody class="listRow">{clients.map(this.renderClient)}</tbody>
</tr>
</Table>
</Container>
);
}
}

Getting Json using Axios and iterating over data in ReactStrap Table

I am trying to get data from jsonplaceholder via axios and iterate over that data and put that data into a reactstrap table. I am getting the error: Expected an assignment or function call and instead saw an expression. I'm not entirely sure what I am doing wrong here. Any help is greatly appreciated.
Here is my code:
render() {
const data = axios.get("https://jsonplaceholder.typicode.com/todos")
.then(response =>
this.data = response.data,
this.data.forEach((item) => {
<tr>
<td>{item.userId}</td>
<td>{item.id}</td>
<td>{item.title}</td>
<td>{item.completed}</td>
</tr>
})
)
return (
<div className="App">
<header className="App-header">
<Table>
<thead>
<tr>
<th>
User ID
</th>
<th>
ID
</th>
<th>
Title
</th>
<th>
Completed
</th>
</tr>
</thead>
<tbody>
{
data
}
</tbody>
</Table>
</header>
</div>
);
}
}
The error is where I try to create the table row <tr> tags in my data variable.
You should use lifecycle methods to load your data from API and store them in a state and render them when the state is updated.
Try this
import React, { Component } from 'react';
import axios from 'axios';
class Example extends Component {
constructor(props) {
super(props);
this.state = {
todos: []
}
}
componentDidMount() {
axios.get("https://jsonplaceholder.typicode.com/todos")
.then(response => {
this.setState({
todos: this.data
});
})
}
render() {
const { todos = [] } = this.state;
return (
<div className="App">
<header className="App-header">
<Table>
<thead>
<tr>
<th>User ID</th>
<th>ID</th>
<th>Title</th>
<th>Completed</th>
</tr>
</thead>
<tbody>
{todos.length ?
todos.map(todo => (
<tr>
<td>{todo.userId}</td>
<td>{todo.id}</td>
<td>{todo.title}</td>
<td>{todo.completed}</td>
</tr>
))
:
(<tr>
<td>-</td>
<td>-</td>
<td>-</td>
<td>-</td>
</tr>)
}
</tbody>
</Table>
</header>
</div>
);
}
}
export default Example;
The mistake is here:
axios.get('https://jsonplaceholder.typicode.com/todos').then(response => {
console.log(response);
this.setState({
todos: response.data, // you have it as this.data not response
});
});

Update a component list after deleting record

I have a component. It displays a list of records. You can click the delete icon, and as soon as you go to a different page and return to the list, the record is no longer there. How do I remove the record from the list without going to a different page?
I've tried using componentWillUpdate() and componentDidUpdate() and placing my getTerritoryGeographies(this.props.params.id) in those functions, but those functions keep calling the data and do not stop. I'm restricted to API limits.
import React, { Component, PropTypes} from 'react';
import { Link } from 'react-router';
import { connect } from 'react-redux';
import { reduxForm } from 'redux-form';
import { getTerritoryGeographies, deleteTerritoryGeography } from '../actions/index';
import TerritoryTabs from './territory-tabs';
class TerritoryGeographyList extends Component {
componentWillMount() {
//console.log('this is the child props (TerritoryGeographyList)');
console.log(this.props);
this.props.getTerritoryGeographies(this.props.params.id);
}
componentDidMount() {
console.log('componentDidMount');
}
componentWillUpdate() {
console.log('componentWillUpdate');
this.props.getTerritoryGeographies(this.props.params.id);
}
componentDidUpdate() {
console.log('componentDidUpdate');
}
onDeleteClick(id) {
this.props.deleteTerritoryGeography(id);
}
static contextTypes = {
router: PropTypes.object
}
renderTerritoryGeographyList() {
return this.props.territoryGeographies.map((geography) => {
return (
<tr key={geography.Id}>
<th scope="row" data-label="Country">
<div className="slds-truncate">{geography.tpslead__Country__c}</div>
</th>
<td data-label="State/Provice">
<div className="slds-truncate">{geography.tpslead__State__c}</div>
</td>
<td data-label="Postal Start">
<div className="slds-truncate">{geography.tpslead__Zip_Start__c}</div>
</td>
<td data-label="Postal End">
<div className="slds-truncate">{geography.tpslead__Zip_End__c}</div>
</td>
<td className="slds-text-align--right" data-label="Action">
<button className="slds-button slds-button--icon" title="edit">
<svg className="slds-button__icon" aria-hidden="true">
<use xlinkHref={editIcon}></use>
</svg>
<span className="slds-assistive-text">Edit</span>
</button>
<button onClick={() => this.onDeleteClick(geography.Id)} className="slds-button slds-button--icon" title="delete" data-aljs="modal" data-aljs-show="PromptConfirmDelete">
<svg className="slds-button__icon" aria-hidden="true">
<use xlinkHref={deleteIcon}></use>
</svg>
<span className="slds-assistive-text">Delete</span>
</button>
</td>
</tr>
);
});
}
render() {
return (
<TerritoryTabs id={this.props.params.id} listTab="geography">
<Link to={"territory/" + this.props.params.id + "/geography/new"} className="slds-button slds-button--brand">
Add New Geography
</Link>
<table className="slds-table slds-table--bordered slds-table--cell-buffer slds-m-top--large">
<thead>
<tr className="slds-text-title--caps">
<th scope="col">
<div className="slds-truncate" title="Country">Country</div>
</th>
<th scope="col">
<div className="slds-truncate" title="State/Provice">State/Provice</div>
</th>
<th scope="col">
<div className="slds-truncate" title="Postal Start">Postal Start</div>
</th>
<th scope="col">
<div className="slds-truncate" title="Postal End">Postal End</div>
</th>
<th className="slds-text-align--right" scope="col">
<div className="slds-truncate" title="Action">Action</div>
</th>
</tr>
</thead>
<tbody>
{this.renderTerritoryGeographyList()}
</tbody>
</table>
</TerritoryTabs>
);
}
}
function mapStateToProps(state) {
//console.log(state);
return { territoryGeographies: state.territoryGeographies.all
};
}
export default connect(mapStateToProps, { getTerritoryGeographies, deleteTerritoryGeography })(TerritoryGeographyList);
UPDATE: I figured out how do remove it by updating my onDeleteClick(), but it seems unnecessarily heavy for a react app. Thoughts?
onDeleteClick(id) {
this.props.deleteTerritoryGeography(id);
var geographyIndex = this.props.territoryGeographies.findIndex(x => x.Id==id)
this.setState(state => {
this.props.territoryGeographies.splice(geographyIndex, 1);
return {territoryGeographies: this.props.territoryGeographies};
});
}
Please post your action and reducer so that we can see what you are doing on the Redux side.
If you are renderings a list from data that is in the Redux store, you can use React-Redux's connect Higher Order Function to wrap the component, thus enabling access to the store as component props. So that part looks correct.
When you are firing the action creator, you should be passing in the id of the data that you would like deleted, and in your reducer, something like this:
case 'DELETE_TERRITORY':
const territoryId = action.data;
return state.filter(territory => territory.id !== territoryId);
When the reducer returns the new, filtered array, your component should update with the list minus the territory you just deleted.
This code controls whether the deletion operation is performed correctly. Returns the state to the first state if the deletion operation fails
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
handleDelete = async productId => {
const originalProducts = this.state.products;
const products = this.state.products.filter(p => productId !== p.productId);
this.setState({ products });
try {
const result = await deleteProduct(productId);
if (result.status === 200) {
// codes goes here. for example send notification
}
}
catch (ex) {
if (ex.response && ex.response.status === 404) {
// codes goes here. for example send notification
}
this.setState({ products: originalProducts });
}
}
reactjs

Resources