**Hello Guys, i create a table in MyProjectList.js file for displaying project data now i want, If user Click on table row then i want to pass this clicked Project Id to Collection.js file to use in query to compare.
*this is MyProjectList.js file.
import React from "react";
import { useEffect, useState } from "react";
import { Table } from "react-bootstrap";
import axios from "axios";
import _ from "lodash";
import { useSelector } from "react-redux";
import { useNavigate } from "react-router-dom";
const pageSize = 10;
export default function MyProjectsList() {
let navigate = useNavigate();
const [projects, setProjects] = useState();
const [paginatedProject, setPaginatedProject] = useState();
const [currentPage, setCurrentPage] = useState(1);
const userState = useSelector(state=> state.loginUserReducer)
const {currentUser} =userState;
const coordinatorId = currentUser.id;
useEffect(() => {
axios.post("http://localhost:4000/coordinatorsProjects",
{
coordinatorId : coordinatorId
}).then((res) => {
console.log(res.data,'==>>> this is coordinator projects');
setProjects(res.data);
setPaginatedProject(_(res.data).slice(0).take(pageSize).value());
});
}, [coordinatorId]);
const pageCount = projects ? Math.ceil(projects.length / pageSize) : 0;
const pages = _.range(1, pageCount + 1);
const pagination = (pageNo) => {
setCurrentPage(pageNo);
const startIndex = (pageNo - 1) * pageSize;
const paginatedProject = _(projects)
.slice(startIndex)
.take(pageSize)
.value();
setPaginatedProject(paginatedProject);
};
//***using this function i am nevigate user to colletion.js component. how to pass project id this?
const onRowClick = async (e) => {
navigate("/coordinators/collection")
console.log(e)
}
return (
<>
<div className="container">
{/* {loading && (<Loading/>)} */}
{/* {error && alert("Error occured to get data")} */}
{!paginatedProject ? (
"ERROR: Data Not Found. Please check your internet connection!"
) : (
<Table className="table table-hover table-light table-bordered shadow">
<thead className="thead-dark">
<tr>
<th scope="col">Project Name</th>
<th scope="col">Start Date</th>
<th scope="col">End Date</th>
<th scope="col">Budget Rs.</th>
<th scope="col">Remaining Rs.</th>
</tr>
</thead>
<tbody>
{paginatedProject.map((user, _id) => (
<tr onClick={ onRowClick } key={_id}>
<td>{user.projectName}</td>
<td>{user.startDate}</td>
<td>{user.endDate}</td>
<td>{user.budget}</td>
<td>{user.remaining}</td>
</tr>
))}
</tbody>
</Table>
)}
<nav className="d-flex pagination justify-content-center ">
<ul className="pagination ">
{pages.map((page) => (
<li
className={
page === currentPage ? "page-item active" : "page-item"
}
>
<p className="page-link" onClick={() => pagination(page)}>
{page}
</p>
</li>
))}
</ul>
</nav>
</div>
</>
);
}
*this is Collection.js file.
import React from 'react';
import { useEffect, useState } from "react";
import { Table } from "react-bootstrap";
import axios from "axios";
import _ from "lodash";
const pageSize= 10;
export default function Collection () {
const [donors, setDonors] = useState()
const [paginatedDonors, setPaginatedDonors] = useState()
const [currentPage, setCurrentPage] = useState(1)
useEffect(() => {
axios.post("http://localhost:4000/coordinatorsCollection",
{
projectID : "7"
}).then((res)=>{
console.log(res.data);
setDonors(res.data);
setPaginatedDonors(_(res.data).slice(0).take(pageSize).value());
});
}, []);
const pageCount= donors? Math.ceil(donors.length/pageSize) :0;
const pages = _.range(1, pageCount+1)
const pagination= (pageNo) =>{
setCurrentPage(pageNo)
const startIndex = (pageNo -1) * pageSize;
const paginatedDonors = _(donors).slice(startIndex).take(pageSize).value();
setPaginatedDonors(paginatedDonors)
}
return (
<>
<div className='container'>
<h3 align="center">Collection of users</h3>
{/* {loading && (<Loading/>)} */}
{/* {error && alert("Error occured to get data")} */}
{!paginatedDonors ? ("ERROR: Data Not Found. Please check your internet connection!"):(
<Table className="table table-hover table-light table-bordered shadow">
<thead className="thead-dark">
<tr>
<th scope="col">Donor Name</th>
<th scope="col">Contact No</th>
<th scope="col">Amount</th>
<th scope="col">Project</th>
<th scope="col">Project Budget</th>
<th scope="col">Donate Date.</th>
</tr>
</thead>
<tbody >
{paginatedDonors.map((donors, id) => (
<tr key={id}>
<td>{donors.name}</td>
<td>{donors.mobileNo}</td>
<td>{donors.amount}</td>
<td>{donors.project}</td>
<td>{donors.projectBudget}</td>
<td>{donors.donateDate}</td>
</tr>
))}
</tbody>
</Table>
)}
<nav className="d-flex pagination justify-content-center ">
<ul className="pagination ">
{
pages.map((page)=>(
<li className={
page === currentPage ? "page-item active" : "page-item"
}>
<p className="page-link"
onClick={()=>pagination(page)}
>{page}</p></li>
) )
}
</ul>
</nav>
</div>
</>
)
};
temporarily i am sending '7' (hard coded) to the api to check and it working fine. But i want clicked project id in this.
thank you!!!
You need only one id. You can get this id when you mapping projects in MyProjectList.js file at this line paginatedProject.map((user, _id) => ().
Just get projectid from user and then send it into onClick like this:
onCLick = {(e) => onRowClick(e, user.projectId)}
If I were you I would use react context for this situation because your issue is the meaning of using react context; React context is a general state that you can set or edit or use your general state in all your components easily
Related
i'm new to reactjs and i'm trying to make a table that shows the information from a array of objects and have a button of delete and an input to search among the users. The delete button is working correctly when i'm not searching anything, but when i'm searching it doesn't delete the corretly row, and deletes only the first one. I see that it is because the arrays that show the table are different with and without the search being used but I don't know how to make it work.
this is the component of the table:
import { formatDate } from "../../utils/formatDate";
import "./table.css";
import { useState } from "react";
function Table(props) {
const { headerData, bodyData, type, removeItem} = props;
const isUser = type === "user";
const buildTableItems = () => {
return bodyData.map((item, index) => (
<tr className="data-tr">
<td>{item.name}</td>
<td>{item.email}</td>
<td>{item.occupation}</td>
<td>{formatDate(item.birthday)}</td>
<td>
<button className="delete-button" onClick={() => removeItem(index)}>
Delete
</button>
</td>
</tr>
));
};
return (
<div className="user-data">
<table className="user-table">
<thead>
<tr className="data-th">
{headerData.map((headerTable) => (
<th >{headerTable}</th>
))}
</tr>
</thead>
<tbody>{buildTableItems()}</tbody>
</table>
</div>
);
}
export default Table;
Here the component of the search bar:
import "./searchBar.css"
function SearchBar({ searchedData, onSearch }) {
return (
<div className="search-bar">
<label>Search</label>
<input type="text" placeholder="Search User" value={searchedData} onChange={e => onSearch(e.target.value)} />
</div>
);
}
export default SearchBar;
and here is the home:
import "./Home.css";
import React, { useEffect, useState } from "react";
import Header from "../components/Header/Header";
import Table from "../components/Table/Table";
import AddData from "../components/AddData/AddData";
import SearchBar from "../components/SearchBar/SearchBar";
import { userArr } from "../mock/users";
const Home = () => {
const headerUser = ["Name", "Email", "Occupation", "Birthday"];
const [newUserArr, setNewUserArr] = useState(userArr);
const [searchedItem, setSearchedItem] = useState("");
const searchedArray = newUserArr.filter((item) => {
if (item.name.toLowerCase().includes(searchedItem.toLowerCase())) {
return true;
}
});
function onSearch(e) {
setSearchedItem(e);
}
const addDataToArr = (form) => {
setNewUserArr([...newUserArr, form]);
};
const deleteData = (indexUserArr) => {
let restOfDataArray = newUserArr.filter(
(element, ind) => ind !== indexUserArr
);
setNewUserArr(restOfDataArray);
};
return (
<>
<Header />
<SearchBar searchedData={searchedItem} onSearch={onSearch} />
<Table
type="user"
headerData={headerUser}
bodyData={newUserArr}
removeItem={(index) => deleteData(index)}
/>
<AddData saveData={(val) => addDataToArr(val)} />
</>
);
};
export default Home;
thank you
If you have ID in your user data then use that instead of index or create id keywords using concatenate with your values here is examples.
import { formatDate } from "../../utils/formatDate";
import "./table.css";
import { useState } from "react";
function Table(props) {
const { headerData, bodyData, type, removeItem} = props;
const isUser = type === "user";
const buildTableItems = () => {
return bodyData.map((item, index) => (
<tr className="data-tr">
<td>{item.name}</td>
<td>{item.email}</td>
<td>{item.occupation}</td>
<td>{formatDate(item.birthday)}</td>
<td>
<button className="delete-button" onClick={() => removeItem(`${item.name}${item.email}${item.occupation}`)}>
Delete
</button>
</td>
</tr>
));
};
return (
<div className="user-data">
<table className="user-table">
<thead>
<tr className="data-th">
{headerData.map((headerTable) => (
<th >{headerTable}</th>
))}
</tr>
</thead>
<tbody>{buildTableItems()}</tbody>
</table>
</div>
);
}
export default Table;
And here is your delete method ${item.name}${item.email}${index}
const deleteData = (data) => {
let restOfDataArray = newUserArr.filter(
(element, ind) => `${element.name}${element.email}${element.occupation}` !== data
);
setNewUserArr(restOfDataArray);
};
This will fixed your problem. If this doesn't work then you need to use ID to resolve this problem. There is a possibility that ${item.name}${item.email}${item.occupation} can be duplicates.
Never use index ever for deleting or any other operations. Use always ID.
Quick help needed! I have list of data rendered in a table from an API. I need this list of data to be paginated into small list of data.
Here is the code for VendorsDetail.js which displays list of data in a table
import React, { useState, useEffect } from "react";
import HelpOutlineIcon from "#mui/icons-material/HelpOutline";
import axios from "axios";
import VendorDetailsBrief from "./VendorDetailsBrief";
import Pagination from "./Pagination";
const VendersDetail = ({ textMe }) => {
const [data, setData] = useState({});
const foo = "cpe:2.3:a:oracle:peoplesoft_enterprise:8.22.14";
const baseURL =
"https://services.nvd.nist.gov/rest/json/cves/1.0?cpeMatchString=" + foo;
useEffect(() => {
axios
.get(baseURL)
.then((response) => {
setData(response.data);
})
.then(
(response) => {},
(err) => {
alert(err);
}
);
}, []);
const DisplayData = data?.result?.CVE_Items?.map((vender) => {
return (
<tr>
<td className="color_id font-semibold">
{vender?.cve?.CVE_data_meta?.ID}
</td>
<td className="w-96">
{vender?.cve?.description?.description_data?.[0]?.value}
</td>
<td>{vender?.impact?.baseMetricV2?.exploitabilityScore}</td>
<td>{vender?.impact?.baseMetricV2?.severity}</td>
<td>{vender?.impact?.baseMetricV2?.impactScore}</td>
</tr>
);
});
return (
<div className="z-100 flex justify-center items-center mt-10">
<div className="text-black">
<div className="rounded overflow-hidden flex justify-center items-center">
<table class="table table-striped ">
<thead>
<tr>
<th>Vuln ID</th>
<th>Description Data</th>
<th>Exploitability Score</th>
<th>Severity</th>
<th>Impact Score</th>
</tr>
</thead>
<tbody>{DisplayData}</tbody>
</table>
</div>
</div>
</div>
);
};
export default VendersDetail;
Pagination.js
import React from "react";
const Pagination = ({ postsPerPage, totalPosts, paginate }) => {
const pageNumbers = [];
for (let i = 1; i <= Math.ceil(totalPosts / postsPerPage); i++) {
pageNumbers.push(i);
}
return (
<nav>
<ul className="pagination">
{pageNumbers.map((number) => (
<li key={number} className="page-item">
<a onClick={() => paginate(number)} href="!#" className="page-link">
{number}
</a>
</li>
))}
</ul>
</nav>
);
};
export default Pagination;
How can I implement pagination in this particular data list? Thanks
Create Parent Component with logic to get data from URL and pagination onCLick handler.
Parent Component should render VendorsDetail component and Pagination component.
Pass data to be displayed to VendorsDetails component and getSubsequentData handler to Pagination component.
If user click on specific page number, call getSubsequentData handler with specific argument, that updates the state of the parent component, which will updates VendorsDetail component.
const ParentComponent = () => {
const [data, setData] = useState({})
useEffect = (() => {
// axios call to get initial data from the URL
})
getSubsequentData = (URL) => {
// axios call to get data based on the URL.
// LInk this to pagination onClick
}
return(
<VendorsDetail data={data} />
<Pagination getNextData={getSubsequentData}/>
)
}
I am new to React and trying to develop my first web application. What I am trying to achieve is pretty basic. I am trying to fetch some data from an API and display it in a table. To the table I am trying to add pagination so that all the records are not displayed on the same screen. I have added the page numbers but when I click on any of the page number links, the correct data in the table gets loaded but the table disappears immediately. I have no clue why this is happening. Here is my code below:
Basket.js
import React, { useState, useEffect } from "react";
import axios from "axios";
import Posts from "../Posts";
import Pagination from "../Pagination";
const Basket = () => {
const [posts, setPosts] = useState([]);
const [loading, setLoading] = useState(false);
const [currentPage, setCurrentPage] = useState(1);
const [postsPerPage] = useState(10);
useEffect(() => {
const fetchPosts = async () => {
setLoading(true);
const res = await axios.get("http://192.168.29.135:8000/aysle/baskets/");
setPosts(res.data);
setLoading(false);
};
fetchPosts();
}, []);
//Get current posts
const indexOfLastPost = currentPage * postsPerPage;
const indexOfFirstPost = indexOfLastPost - postsPerPage;
const currentPosts = posts.slice(indexOfFirstPost, indexOfLastPost);
//Change Page
const paginate = (pageNumber) => setCurrentPage(pageNumber);
//console.log(posts);
return (
<div>
<Posts posts={currentPosts} loading={loading} />
<Pagination
postsPerPage={postsPerPage}
totalPosts={posts.length}
paginate={paginate}
/>
</div>
);
};
export default Basket;
To display the data in tabular form am using the below code:
Posts.js:
import React from "react";
import edit from "../images/edit.png";
import del from "../images/delete.png";
import "./Basket/basket.scss";
const Posts = ({ posts, loading }) => {
if (loading) {
return <h2>Loading All Baskets....</h2>;
}
return (
<table className="basket-view">
<thead>
<tr id="Baskettr">
<th id="Basketth" colSpan="4">
Here are your Listings...
</th>
</tr>
<tr id="Baskettr">
{/* <th id="Basketth">Id</th> */}
<th id="Basketth">Basket Name</th>
<th id="Basketth">Basket Creation Date</th>
<th id="Basketth">Basket Modified Date</th>
<th id="Basketth">Action</th>
</tr>
</thead>
<tbody id="Baskettbody">
{posts ? (
posts.length > 0 ? (
posts.map((post, index) => {
return (
<tr id="Baskettr" key={index}>
{/* <td id="Baskettd">{basket.id}</td> */}
<td id="Baskettd">{post.basket_name}</td>
<td id="Baskettd">{post.basket_creation_date}</td>
<td id="Baskettd">{post.basket_modified_date}</td>
<td>
<button id="delBtn" title="Edit">
<img src={edit} id="BtnImg" alt="Edit" />
</button>
<button id="editBtn" title="Delete">
<img src={del} id="BtnImg" alt="Delete" />
</button>
</td>
</tr>
);
})
) : (
<tr id="Baskettr">
<td id="Baskettd">No Records to Show...</td>
</tr>
)
) : (
0
)}
</tbody>
</table>
);
};
export default Posts;
And finally, for pagination I am using the following code:
import React from "react";
const Pagination = ({ postsPerPage, totalPosts, paginate }) => {
const pageNumbers = [];
//console.log(totalPosts);
for (let i = 1; i <= Math.ceil(totalPosts / postsPerPage); i++) {
pageNumbers.push(i);
}
return (
<nav>
<ul className="pagination">
{pageNumbers.map((number) => (
<li key={number} className="page-item">
<a onClick={() => paginate(number)} href="!#" className="page-link">
{number}
</a>
</li>
))}
</ul>
</nav>
);
};
export default Pagination;
Please help me to rectify this issue. Thanks a lot for your time in advance. Here is the CodeSandBoxLink
It's all because of the href attribute "!#" in the tag. Because of it, there is a transition to a new page and all data fetched again.
You can use <button/> instead of <a/> and style it with css. example
i created an app using react js which get te data from a graphql endpoint .
the data is displayed in a table and i ant to add a search function .
when the attribute name match the input in the search field only the roes that contains that name will stay displayed so basically i ant to hide the other rows
search component :
import React, { useState } from 'react'
const Search = ({ getQuery }) => {
const [text, setText] = useState('')
const onChange = (q) => {
setText(q)
getQuery(q)
}
return (
<section className='search'>
<form>
<input
type='text'
className='form-control'
placeholder='Search characters'
value={text}
onChange={(e) => onChange(e.target.value)}
autoFocus
/>
</form>
</section>
)
}
export default Search
orders list :
import React , { useState, useEffect } from 'react'
import { gql, useQuery } from '#apollo/client';
import Table from 'react-bootstrap/Table'
import Moment from 'react-moment';
import moment from "moment";
import { Link } from 'react-router-dom';
import Row from 'react-bootstrap/Row'
import Col from 'react-bootstrap/Col'
import { DangerousChangeType } from 'graphql';
import Search from './Search'
import Button from 'react-bootstrap/Button'
const GET_All_Orders = gql`
query Orders($input1: PaginationInput) {
Orders(input: $input1){
pageInfo {
hasNextPage
hasPreviousPage
}
edges{
cursor
node {
id
closed
email
createdAt
updatedAt
cancelledAt
displayFinancialStatus
displayFulfillmentStatus
lineItems{
edges{
node {
customAttributes{
key
value
}
id
quantity
title
variant{
id
image {
altText
id
src
}
title
weight
weightUnit
price
}
}
}
}
shippingAddress {
name
}
phone
subtotalPrice
totalPrice
totalRefunded
totalTax
processedAt
}
}
}
}
`;
export default function AllOrders({ input1 }) {
const { loading, error, data , fetchMore} = useQuery(GET_All_Orders, {
variables: {"input1": {
"num": 20,
}}
,
});
let date = new Date()
const [query, setQuery] = useState('')
if (loading) return <h4>読み込み中...</h4>;
if (error) return `Error! ${error}`;
return( <div>
<Row >
<Col xs={10}> <h5>すべての注文</h5></Col>
<Col><h5> 日付 : <Moment format="YYYY/MM/DD">
{ date}
</Moment> </h5></Col>
</Row>
<br/>
<Table responsive hover size="sm">
<thead>
<tr>
<th className="allOrders">注文日</th>
<th className="allOrders">名前</th>
<th className="allOrders">注文者メールアドレス</th>
<th className="allOrders" >配送状態</th>
<th className="allOrders" >支払状況</th>
<th className="allOrders" >合計金額</th>
<th className="allOrders" >詳細</th>
</tr>
</thead>
<tbody>
{data.Orders.edges.map(({ edges ,node :{id , createdAt , displayFulfillmentStatus , displayFinancialStatus , totalPrice , email , shippingAddress: {
name
} }}) => (
<tr key={id}>
<td> <Moment format="YYYY/MM/DD">
{createdAt}
</Moment></td>
<td>{ name} </td>
<td>{ email} </td>
{displayFulfillmentStatus == "FULFILLED" ? <td className="success">配送済み</td> : <td className="failed">未配送</td>}
{displayFinancialStatus == "PAID" ? <td>支払済み</td> : <td>未払い</td> }
<td>{totalPrice} </td>
<td>
<Link to={`/orders/${id}`} className="btn btn-light">
詳細
</Link></td>
</tr>
))}
</tbody>
</Table>
<div className="text-center">
<Button
variant="light"
onClick={() => {
fetchMore({
variables: {"input1": {
"num": 20,
"cursor": data.Orders.edges[data.Orders.edges.length - 1].cursor }},
updateQuery: (prevResult, { fetchMoreResult }) => {
fetchMoreResult.Orders.edges = [
...prevResult.Orders.edges,
...fetchMoreResult.Orders.edges
];
return fetchMoreResult;
}
});
}}
>
もっと
</Button>
</div>
</div>
)}
when i try it inside the map function like :
{query === name ? <td> {name}</td> : null }
it works fine but i don't know how to deal with the rows and that logic .
I am trying to create search with react redux but i am confuse how it works with map data.
so here is my code:
searchaction.js
export const SEARCH = 'SEARCH'
const search = (term) => {
return {
type:SEARCH,
term
}
}
searchreducer.js:
import {SEARCH} from '../searchaction'
// import {games} from './games'
export const searchreducer = (state = '', action) => {
switch (action.type){
case SEARCH:
return action.term
default:
return state;
}
}
rootreducer.js
import {combineReducers} from 'redux';
import {games} from './reducers/games';
import {searchreducer} from './reducers/searchreducer';
export default combineReducers({
games,
search:searchreducer
});
gamelist.js in which i am getting data from api:
import React from 'react';
import PropTypes from 'prop-types';
import {Link} from 'react-router-dom';
import SearchReport from './reportsearch';
// import {deleteReports} from './actions';
export const GamesList = ({games, deleteReports}) => {
const emptyMessage = (
<p>There are no games yet in your collection.</p>
)
const gamesList = (
<div className="row">
<table>
<thead>
<tr>
<th>Registraton date</th>
<th>Registraton No</th>
<th>Paitient Name</th>
<th>Gender</th>
<th>Age</th>
<th>Refer By</th>
<th>Test Requested</th>
<th>Report Status</th>
<th>Total Amount</th>
<th>Receipt Amount</th>
<th>Balance Amount</th>
<th></th>
<th></th>
</tr>
</thead>
{games.map((reports,i) =>
<tbody key={i}>
<tr>
<td>{reports.reg_date}</td>
<td>{reports.reg_no}</td>
<td>{reports.patient_name}</td>
<td>{reports.gender}</td>
<td>{reports.age}</td>
<td>{reports.refer_by}</td>
<td>{reports.test_request}</td>
<td>{reports.report_status}</td>
<td>{reports.total_amt}</td>
<td>{reports.receipt_amt}</td>
<td>{reports.bal_amt}</td>
<td><Link to={`/games/${reports.r_id}`} id={reports.r_id} className="btn-floating btn-large blue"><i class="large material-icons">edit</i></Link></td>
<td><button className="btn-floating btn-large red" onClick={() => deleteReports(reports.r_id)} deleteReports={deleteReports}><i class="large material-icons">delete</i></button></td>
</tr>
</tbody>
)}
</table>
</div>
)
return (
<div>
{games.length === 0 ? emptyMessage : gamesList}
</div>
)
}
GamesList.propTypes = {
games: PropTypes.array.isRequired,
deleteReports: PropTypes.func.isRequired
}
gamepage.js where i am rendering components gamelist.js and searchreport:
class GamesPage extends React.Component{
componentDidMount(){
this.props.fetchGames();
}
render(){
return (
<div>
<h1>Report List</h1>
<SearchReport />
<GamesList games={this.props.games} deleteReports={this.props.deleteReports} />
</div>
)
}
}
GamesPage.propTypes = {
games: PropTypes.array.isRequired ,
fetchGames: PropTypes.func.isRequired,
deleteReports: PropTypes.func.isRequired
}
const mapStateToProps = (state) =>{
return {
games:state.games
}
}
export default connect(mapStateToProps, {fetchGames, deleteReports} )(GamesPage)
thats my code i am confuse how this map data will connect with search input and filter it.
Thanks in advance
What you need is a selector. So basically:
const mapStateToProps = (state) =>{
return {
games: getSearchResults(state)
}
}
getSearchResults can just filter the array directly or enhance it with the reselect library mentioned in the documentation. But that would be more of an implementation detail. Here an example of just a filter:
const getSearchResults = (state) => {
return state.games.filter((game) => game.includes(state.search)
}