How to use params.(key) to get specific data for each route? - javascript

I want to build a car list app that will show a list of cars, and when I click on a car's details button, it will route it to another component/page that will show the details of cars.
I can get the key (vin for me) but I want to get the details of the car for each key(vin) on this page.It's like http://localhost:3000/cars/WAUZZZ4G6FN052847= key. So when a car's key will show up, all details will come due to their key number. Thank you.
index.html
import React from "react";
import ReactDOM from "react-dom/client";
import "./index.css";
import App from "./App";
import { BrowserRouter, Routes, Route, Outlet, } from "react-router-dom";
import DummyComponent from "./components/DummyComponent";
import CarDetails from "./pages/CarDetails";
import { Home } from "#mui/icons-material";
import Cars from "./pages/Cars";
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
<BrowserRouter>
<Routes>
<Route path="/" element={<App />} />
<Route path="/cars" element={<Outlet />} >
<Route path="list" element={<Cars />} />
<Route path=":vin" element={<CarDetails />} />
</Route>
<Route path="Home" element={<Home />} />
<Route path="DummyComponent" element={<DummyComponent />} />
</Routes>
</BrowserRouter>
);
Cars.js
import axios from "axios";
import React, { useEffect, useState } from "react";
import List from '#mui/material/List';
import ListItem from '#mui/material/ListItem';
import ListItemButton from '#mui/material/ListItemButton';
import ListItemText from '#mui/material/ListItemText';
import { Link } from "react-router-dom";
const App = () => {
const [cars, setCars] = useState([])
const getCarData = async () => {
try {
const data = await axios.get("https://react-challenge-api.azurewebsites.net/vehicles")
setCars(data.data)
}
catch (e) {
console.log(e)
}
}
useEffect(() => {
getCarData()
}, [])
return (
<div className="App">
<List sx={{ width: '100%', maxWidth: 600, bgcolor: 'background.paper' }}>
{cars.map((car) => (
<ListItemButton key={car.vin}>
<ListItem
key={car.vin}
disableGutters
secondaryAction={
<ListItemButton >
<Link to={`/cars/${car.vin}`}>details</Link>
</ListItemButton>
}
>
<ListItemText key={car.vin} primary={car.model_variant} />
</ListItem>
</ListItemButton>
))
}
</List >
</div >
);
};
export default App;
CarDetails.js (I want to show each data in this component, I used params but I don't know how to get data due to params.
import { useParams } from "react-router-dom";
const CarDetails = () => {
let params = useParams();
return (
<>
<h1>car</h1>
<ul>
this is your {params.vin}
</ul>
</>
)
}
export default CarDetails;

I would suggest moving the car data fetching into a layout route and pass the cars state down in an Outlet context.
Example:
Cars - Handles fetching the car data and passes the cars state along to nested routes via the Outlet component's context.
const Cars = () => {
const [cars, setCars] = useState([]);
const getCarData = async () => {
try {
const data = await axios.get(
"https://react-challenge-api.azurewebsites.net/vehicles"
);
setCars(data.data);
} catch (e) {
console.log(e);
}
};
useEffect(() => {
getCarData();
}, []);
return <Outlet context={{ cars }} />;
};
CarList - Reads the cars state from the Outlet context and renders the list.
const CarList = () => {
const { cars } = useOutletContext();
return (
<List sx={{ width: "100%", maxWidth: 600, bgcolor: "background.paper" }}>
{cars.map((car) => (
<ListItemButton key={car.vin}>
<ListItem
key={car.vin}
disableGutters
secondaryAction={
<ListItemButton>
<Link to={`/cars/${car.vin}`}>details</Link>
</ListItemButton>
}
>
<ListItemText key={car.vin} primary={car.model_variant} />
</ListItem>
</ListItemButton>
))}
</List>
);
};
CarDetails - Takes the vin route path param and the cars array from the outlet context and searches for a matching car object.
const CarDetails = () => {
const { vin } = useParams();
const { cars } = useOutletContext();
const car = cars.find((car) => car.vin === vin);
if (!car) {
return "No car matches this VIN";
}
return (
<>
<h1>{car.model_variant}</h1>
<ul>
<li>Body: {car.body_type}</li>
<li>Doors: {car.doors}</li>
<li>Fuel: {car.fuel_type}</li>
<li>VIN: {car.vin}</li>
<li>Registration #: {car.regno}</li>
<li>Transmission: {car.transmission_type}</li>
</ul>
</>
);
};
Routes
<Routes>
<Route path="/" element={<App />} />
<Route path="/cars" element={<Cars />}> // <-- layout route renders outlet
<Route path="list" element={<CarList />} />
<Route path=":vin" element={<CarDetails />} />
</Route>
<Route path="Home" element={<Home />} />
<Route path="DummyComponent" element={<DummyComponent />} />
</Routes>

Related

How can i get some value from other page js?

I have two page: Header.js and Post.js. These pages is joined on main page - Home.js. Post.js has button "Buy". This button creates variable with value 0 or 1. This value is saved on local storage with window.localStorage.setItem(). And I Want to take with value and give to Header.js. But when I do this value isn't updated avere time, when I click "buy"
How can I make this?
window.localStorage.setItem('countcart',count);
const sumCount = async () => {
if(count === 0){
setCount(Math.max(count+1,0));
} else{
setCount(Math.max(count-1,0));
}
};
<Button className={styles.buy} onClick={sumCount} variant="contained" endIcon={<ShoppingCartIcon fontSize="small"/>}><div className={styles.buytext}>Buy</div> </Button>
If you want localStorage to update every time count is changed, you should wrap it with a useEffect:
useEffect(() => {
window.localStorage.setItem('countcart',count);
}, [count])
But, this doesn't auto-update the count value in the other component; to do that with localStorage you'd need to use the https://developer.mozilla.org/en-US/docs/Web/API/Window/storage_event
But, a better way for the other component to access count would be to declare count as a state in the parent component and pass its state to the Header.js and Post.js components, e.g.:
// App.js
function App() {
const [count, setCount] = useCount(window.localStorage.getItem('count'));
useEffect(() => {
window.localStorage.setItem('countcart',count);
}, [count])
return (
<>
<Header count={count} setCount={setCount} />
<Post count={count} setCount={setCount} />
</>
)
}
import {Routes, Route} from 'react-router-dom';
import Container from '#mui/material/Container';
import { Header } from './components';
import { Home, FullPost, Registration, AddPost, Login, PostsByTag, Account } from './pages';
import { useDispatch, useSelector } from 'react-redux';
import React, { useState } from 'react';
import { fetchAuthMe, selectIsAuth } from './redux/slices/auth';
function App() {
const dispatch = useDispatch();
const [count, setCount] = useState(window.localStorage.getItem('countcart')? 0 :window.localStorage.getItem('countcart'));
const isAuth = useSelector(selectIsAuth);
React.useEffect(()=>{
dispatch(fetchAuthMe());
window.localStorage.setItem('countcart',count);
},[count])
return (
<>
<Header count={count} setCount={setCount}/>
<Container maxWidth="lg">
<Routes>
<Route path="/" element={<Home count={count} setCount={setCount}/>} />
<Route path="/posts/:id" element={<FullPost />} />
<Route path="/tags/:tag" element={<PostsByTag />} />
<Route path="/posts/:id/edit" element={<AddPost />} />
<Route path="/add-post" element={<AddPost />} />
<Route path="/login" element={<Login />} />
<Route path="/register" element={<Registration />} />
<Route path="/account/:id" element={<Account />} />
</Routes>
</Container>
</>
);
}
export default App;
import React from 'react';
import { Rating,IconButton, Button} from '#mui/material';
import clsx from 'clsx';
import {Link, useNavigate} from 'react-router-dom';
import DeleteIcon from '#mui/icons-material/Clear';
import EditIcon from '#mui/icons-material/Edit';
import EyeIcon from '#mui/icons-material/RemoveRedEyeOutlined';
import CommentIcon from '#mui/icons-material/ChatBubbleOutlineOutlined';
import ShoppingCartIcon from '#mui/icons-material/ShoppingCart';
import styles from './Post.module.scss';
// import { UserInfo } from '../UserInfo';
import { PostSkeleton } from './Skeleton';
import { useDispatch } from 'react-redux';
import { fetchRemovePost } from '../../redux/slices/posts';
export const Post = ({
id,
title,
createdAt,
imageUrl,
user,
viewsCount,
commentsCount,
tags,
children,
isFullPost,
isLoading,
isEditable,
count,
setCount,
}) => {
// const [count, setCount] = React.useState(0);
const dispatch = useDispatch();
const navigate = useNavigate();
if (isLoading) {
return <PostSkeleton />;
}
console.log(count);
window.localStorage.setItem('countcart',count);
const sumCount = async () => {
if(count === 0){
setCount(Math.max(count+1,0));
} else{
setCount(Math.max(count-1,0));
}
};
const onClickRemove = () => {
if(window.confirm('Do you sure want to remove post?')){
dispatch(fetchRemovePost(id));
navigate(0);
}
};
return (
<div className={clsx(styles.root, { [styles.rootFull]: isFullPost })}>
{isEditable && (
<div className={styles.editButtons}>
<Link to={`/posts/${id}/edit`}>
<IconButton color="primary">
<EditIcon />
</IconButton>
</Link>
<IconButton onClick={onClickRemove} color="secondary">
<DeleteIcon />
</IconButton>
</div>
)}
{imageUrl && (
<img
className={clsx(styles.image, { [styles.imageFull]: isFullPost })}
src={imageUrl}
alt={title}
/>
)}
<div className={styles.wrapper}>
<div className={styles.indention}>
<h2 className={clsx(styles.title, { [styles.titleFull]: isFullPost })}>
{isFullPost ? title : <Link to={`/posts/${id}`}>{title}</Link>}
</h2>
<div className={styles.ratingprice}>
<Rating
name="size-small"
value={2.5}
size="small"
precision={0.5}
readOnly
/>
<div className={styles.review}>12 отзывов</div>
</div>
<div className={styles.price}>1150 руб.</div>
{children && <div className={styles.content}>{children}</div>}
<div className={styles.postDetails}>
<ul className={styles.postDetails}>
<li>
<EyeIcon />
<span>{viewsCount}</span>
</li>
<li>
<CommentIcon />
<span>{commentsCount}</span>
</li>
</ul>
<Button className={styles.buy} onClick={sumCount} variant="contained" endIcon={<ShoppingCartIcon fontSize="small"/>}><div className={styles.buytext}>Купить</div> </Button>
</div>
</div>
</div>
</div>
);
};

Dynamic data showing undefined

in my project, I'm trying, when I click a blog in many blogs. then only that blog will open in another route. and I set that route dynamically. and trying to load data using the find method. but that showing undefined. Please help me. below are my all codes.
this is my blogs page
import React, { useEffect, useState } from "react";
import { Card, Col, Row } from "react-bootstrap";
import { Swiper, SwiperSlide } from "swiper/react";
import "swiper/css";
import "swiper/css/pagination";
import { Pagination } from "swiper";
import "./Blog.css";
import ScrollToTop from "react-scroll-to-top";
import { HashLoader } from "react-spinners";
import { Link } from "react-router-dom";
const Blogs = () => {
const [blogs, setBlogs] = useState([])
useEffect(() => {
fetch('https://enigmatic-crag-58614.herokuapp.com/blogs')
.then(res => res.json())
.then(data=>setBlogs(data))
},[])
console.log(blogs);
return (
<div className="container my-5">
<ScrollToTop smooth color="#FE1A00" viewBox="0 0 250 250" />
<h1 className="text-danger">Blogs</h1>
{blogs.length === 0 && (
<h1 className="my-5 py-5">
<HashLoader color={'#FE1A00'} loading={true} size={150} />
</h1>
)}
<Row xs={1} md={3} className="g-4">
{
blogs.map(blog => <Col>
<Card className="shadow">
<Card.Img
variant="top"
src={blog.imageLink}
className="m-3"
/>
<Card.Body>
<h3 className="text-danger">{blog.heading}</h3>
<Card.Text>
{blog.text.slice(0, 200)}...
</Card.Text>
</Card.Body>
<strong className="mb-3">
<Link to={`/single-blog/${blog._id}`} className="see-more">
See More <i className="fas fa-arrow-circle-right"></i>{" "}
</Link>
</strong>
</Card>
</Col>)
}
</Row>
</div>
);
};
export default Blogs;
This is my single blog page
import React, { useEffect, useState } from "react";
import { useParams } from "react-router-dom";
import "./SingleBlog.css";
const SingleBlog = () => {
const { id } = useParams;
const [singleData, setSingleData] = useState([])
useEffect(() => {
fetch('https://enigmatic-crag-58614.herokuapp.com/blogs')
.then(res => res.json())
.then(data => setSingleData(data))
}, [])
console.log(singleData);
const matchedData = singleData.find((singleBlogPost) => singleBlogPost?._id == id)
console.log(matchedData);
return (
<div className="single-blog container w-75">
<div className="image-div mb-5 p-0">
<img
src="https://upload.wikimedia.org/wikipedia/commons/thumb/3/3f/Walking_tiger_female.jpg/220px-Walking_tiger_female.jpg"
alt=""
/>
</div>
<div>
<h1 className="text-danger">Tiger</h1>
<p className="text-start fs-5 fw-700">
The tiger (Panthera tigris) is the largest living cat species and a member of
the genus Panthera. It is most recognisable for its dark vertical stripes on
orange fur with a white underside. An apex predator, it primarily preys on
ungulates such as deer and wild boar. It is territorial and generally a solitary
but social predator, requiring large contiguous areas of habitat, which support
.
</p>
</div>
</div>
);
};
export default SingleBlog;
This is my app.js file
import "./App.css";
import Navigation from "./Components/Navigation/Navigation";
import { BrowserRouter, Route, Routes } from "react-router-dom";
import HomePage from "./Components/HomePage/HomePage";
import AcdmClass from "./Components/AcademicClass/AcdmClass";
import ClassSubject from "./Components/ClassSubjects/ClassSubject";
import Lesson from "./Components/Lesson";
import Footer from "./Components/Footer/Footer";
import Contact from "./Components/Contact/Contact";
import Review from "./Components/Review/Review";
import Blogs from "./Components/Blog/Blogs";
import Signin from "./Components/Signin/Signin";
import Profile from "./Components/Profile/Profile";
import Skills from "./Components/Skills/Skills";
import AuthProvider from "./Contexts/AuthProvider";
import PrivateRoute from "./Components/PrivateRoute/PrivateRoute";
import SingleBlog from "./Components/SingleBlog/SingleBlog";
function App() {
return (
<div className="App">
<AuthProvider>
<BrowserRouter>
<Navigation></Navigation>
<Routes>
<Route path="/" element={<HomePage></HomePage>}></Route>
<Route path="home" element={<HomePage></HomePage>}></Route>
<Route path="blog" element={<Blogs></Blogs>}></Route>
<Route path="contact" element={<Contact></Contact>}></Route>
<Route path="skills" element={<Skills />}></Route>
<Route path="others" element={<Skills />}></Route>
<Route
path="/academic-class"
element={
<PrivateRoute>
<AcdmClass />
</PrivateRoute>
}
/>
<Route
path="/academicclass/:classnumber"
element={
<PrivateRoute>
<ClassSubject />
</PrivateRoute>
}
/>
<Route
path="/lesson"
element={
<PrivateRoute>
<Lesson />
</PrivateRoute>
}
/>
<Route
path="/profile"
element={
<PrivateRoute>
<Profile />
</PrivateRoute>
}
/>
<Route
path="/review"
element={
<PrivateRoute>
<Review />
</PrivateRoute>
}
/>
<Route
path="/single-blog/:id"
element={
<PrivateRoute>
<SingleBlog />
</PrivateRoute>
}
/>
<Route path="/sign-in" element={<Signin />} />
</Routes>
<Footer></Footer>
</BrowserRouter>
</AuthProvider>
</div>
);
}
export default App;
But showing this undefined please see this image
Try putting it in a useEffect like so
useEffect(()=>{
if(singleData){
console.log(singleData);
const matchedData = singleData.find((singleBlogPost) => singleBlogPost?._id == id)
console.log(matchedData);
}
},[singleData,id])
As initially singleData will be undefined and will be set after API call.
In react, The state of the component only get updated at the first time, So you need to tell the react to get the updated state.
In your singleBlog file -
const [singleData, setSingleData] = useState([])
useEffect(() => {
fetch('https://enigmatic-crag-58614.herokuapp.com/blogs')
.then(res => res.json())
.then(data => setSingleData(data))
}, [])
console.log(singleData);
const matchedData = singleData.find((singleBlogPost) => singleBlogPost?._id == id) //This line will never get the data until you ask the react to update the state (means to update the ```singleData``` array.
console.log(matchedData);
So you need to put the same method inside useEffect, and let the useEffect run whenever the state singleData get updated like this ->
useEffect(() => {
const matchedData = singleData.find((singleBlogPost) =>
singleBlogPost?._id == id)
console.log(matchedData);
}, [singleData, id]) //you need to add here all the dependencies, so that whenever these values will change you need to update your singleBlog page.
HERE IS YOUR FINAL CODE OF SINGLE BLOG PAGE ->
const SingleBlog = () => {
const { id } = useParams;
const [singleData, setSingleData] = useState([])
useEffect(() => {
fetch('https://enigmatic-crag-58614.herokuapp.com/blogs')
.then(res => res.json())
.then(data => setSingleData(data))
}, [])
useEffect(() => {
const matchedData = singleData.find((singleBlogPost) =>
singleBlogPost?._id == id)
console.log(matchedData);
}, [singleData, id])
return (
<div className="single-blog container w-75">
<div className="image-div mb-5 p-0">
<img
src="https://upload.wikimedia.org/wikipedia/commons/thumb/3/3f/Walking_tiger_female.jpg/220px-Walking_tiger_female.jpg"
alt=""
/>
</div>
<div>
<h1 className="text-danger">Tiger</h1>
<p className="text-start fs-5 fw-700">
The tiger (Panthera tigris) is the largest living cat species and a member of
the genus Panthera. It is most recognisable for its dark vertical stripes on
orange fur with a white underside. An apex predator, it primarily preys on
ungulates such as deer and wild boar. It is territorial and generally a solitary
but social predator, requiring large contiguous areas of habitat, which support
.
</p>
</div>
</div>
);
};
export default SingleBlog;

How to pass location state and URL params using React-Router?

When I click on the link in the HoverBooks Component to get to a new page where I can render the book location state in Book component, but when I press on it nothing happens. I think the error is in Route:
function App() {
return (
<div className="App">
<Router>
<Switch>
<Route path="/book:/book.Key">
<Book />
</Route>
<Route path="/signin">
<Signin />
</Route>
<Route path="/">
<Header />
<Home />
</Route>
</Switch>
</Router>
</div>
)
}
export default App
import React from 'react'
import { useLocation } from 'react-router-dom'
const Book = () => {
const {
state: { book },
} = useLocation()
console.log({ book })
return (
<div key={book.key}>
<h1>{book.bookName}</h1>
</div>
)
}
export default Book
const HoverBooks = ({ ...book }) => {
const [inHoverBooks, setInHoverBooks] = React.useState(false)
return (
<>
<Link
to={{
pathName: `/book/${book.key}`,
state: {
book,
},
}}
>
<img
onMouseLeave={() => setInHoverBooks(false)}
onMouseEnter={() => setInHoverBooks(true)}
src={book.image}
key={book.key}
/>
</Link>
{inHoverBooks && (
<div className="hover__containter">
<h3>{book.bookName}</h3>
<h2>{book.by}</h2>
<h2>{book.Narreted}</h2>
<h2>{book.length}</h2>
<h2>{book.rating}</h2>
</div>
)}
</>
)
}
export default HoverBooks
Below is the correct form, e.g. /:someName, to define a route with URL params:
<Route path="/book/:bookKey">
<Book />
</Route>
And here is the right syntax to make a Link for the above route:
<Link
to={{
pathname: `/book/SOME_BOOK_KEY`, // replace SOME_BOOK_KEY with some value
state: {
book, // e.g. const book = { key: 'js', bookName: 'Learn JavaScript'}
},
}}
>
<img src="some_src" alt="something" />
</Link>
And you useParams and useLocation react-hooks to access the "URL params" and "location state" in a component:
const Book = () => {
const {
state: { book },
} = useLocation()
const { bookKey } = useParams();
console.log(book, bookKey)
// prints "book" object (from location state) and "bookKey" (from URL params)
return (
<div key={book.key}>
<h1>{book.bookName}</h1>
</div>
)
}
I would suggest you to add typescript to your ReactJS app. It helps you find errors early by doing "static Type-checking".
With react router you need to pass the component you want to render to the Route like this
const ComponentA = (props) => {...}
<Route path="/component-a" component={ComponentA} />
And here is how to link to component a
<Link to="/component-a" >Go to component A</Link>

React router dynamic url no redirecting me to the desired page

I want to access component according to the id of the product.
Here is my Code.
List.jsx
import { Switch, Route, Redirect, withRouter } from "react-router-dom";
import CategoryList from "./CategoryList.jsx";
import ProductList from "./ProductList.jsx";
import React from "react";
import axios from "axios";
const CategoryWithId = ({ match }) => {
console.log("Category", match.params.listId);
<ProductList listId={match.params.listId}></ProductList>;
};
function List() {
const [state, setState] = React.useState([]);
const getList = () => {
axios.get("https://api.growcify.com/dev/category/list").then((res) => {
console.log(res.data);
setState(res.data);
});
};
React.useEffect(() => {
getList();
}, []);
return (
<div className="App">
<Switch>
<Route path="/" component={() => <CategoryList state={state} />} />
<Route path="/product/:listId" component={CategoryWithId} />
<Redirect to="/" />
</Switch>
</div>
);
}
export default withRouter(List);
CategoryList.jsx
import React from "react";
import { Link } from "react-router-dom";
import Grid from "#material-ui/core/Grid";
import Paper from "#material-ui/core/Paper";
import { makeStyles } from "#material-ui/core/styles";
import { Typography } from "#material-ui/core";
const ShowCategory = (props) => {
const classes = useStyles();
const { list } = props;
return (
<Link to={`/product/${list._id}`}>
<Paper className={classes.paper} key={list._id}>
<p style={{ position: "relative", top: "40%" }}>{list.name}</p>
</Paper>
</Link>
);
};
function CategoryList(props) {
const { state } = props;
const classes = useStyles();
return (
<>
<div className={classes.header}>
<Typography variant="h3" style={{ padding: "10px" }}>
List of Categories
</Typography>
</div>
<div className={classes.container}>
<Grid container className={classes.root} spacing={2}>
<Grid item xs={12}>
<Grid container spacing={2}>
{state.map((list, index) => (
<ShowCategory list={list}></ShowCategory>
))}
</Grid>
</Grid>
</Grid>
</div>
</>
);
}
export default CategoryList;
I want that on clicking on Particular category, i should be redirect to /produce/listId.
In the url section, I can see the url with listId but I'm not getting redirected to the desired page related to that url.
Use exact keyword!
<Route exact path="/" component={() => <CategoryList state={state} />} />

React Components are re-rendering Infinite times

All most all components in the router file runs infinitely. Don't know what's the problem.
The ajax request sends infinite GET requests due to this issue.
All the files look like something similar to this.
import React, { useState, useEffect } from "react";
import { connect } from "react-redux";
import { apiCall } from "../handlers/api";
import BasicTable from "../reusable/table";
import { loadFields } from "../store/actions/actionCreators";
const header = [
"Sl.No",
"Item Code",
"Item Name",
"Item Type",
"UoM",
"HSN CODE",
"Specifications",
"Description",
"Brand",
"Price",
];
function Item(props) {
const [fields, setFields] = useState([]);
const [render, setRender] = useState(0);
console.log(fields);
// useEffect(() => {
// props
// .loadFields("/items", 0, 20)
// .then((res) => {
// console.log(res);
// })
// .catch((err) => console.log(err));
// // eslint-disable-next-line react-hooks/exhaustive-deps
// }, []);
apiCall("get", "/product", {})
.then((data) => setFields(data.product))
.catch((err) => console.log(err));
const reRender = () => {
setRender(render + 1);
};
return (
<div>
<h1>Items</h1>
<BasicTable reRender={reRender} header={header} body={fields} />
</div>
);
}
const mapStateToProps = (state) => ({
item: state.Items.fields,
});
export default connect(mapStateToProps, { loadFields })(Item);
Routes file:
Here, all the routes are defined.
import React from "react";
import { Route, BrowserRouter as Router, Switch } from "react-router-dom";
import Home from "./home";
import Supplier from "./supplier";
import Item from "./item";
import Menubar from "./menubar";
import Project from "./project";
import Fields from "./fields";
import User from "./user";
import GeneratePO from "./generatePo";
import PODetails from "./poDetails";
import AddButton from "./addButton";
import AddFields from "./addFields";
import { connect } from "react-redux";
import ViewItems from "../reusable/viewItems";
import AddMaterialForm from "../reusable/addMaterialForm";
import ViewMaterialFormItem from "../reusable/viewMaterialFormItem";
import InventoryHeader from "./inventoryHeader";
import InventoryDetails from "./inventoryDetails";
import AddIntentTable from "../reusable/addIntentTable";
import InventoryIssues from "./inventoryIssues";
import InventoryIndents from "./inventoryIndents";
import ItemForm from "../reusable/itemForm";
import POReport from "../reports/poReport";
function Routers(props) {
return (
<React.Fragment>
<Router>
<header className="width-max navbar">
<Menubar />
<AddButton />
</header>
<Switch>
<Route exact path="/">
<Home />
</Route>
<Route exact path="/users">
<User />
</Route>
<Route exact path="/items">
<Item />
</Route>
<Route exact path="/suppliers">
<Supplier />
</Route>
<Route exact path="/fields">
<Fields />
</Route>
<Route exact path="/projects">
<Project />
</Route>
<Route exact path="/generatepo">
<GeneratePO />
</Route>
<Route exact path="/inventoryheader">
<InventoryHeader />
</Route>
<Route exact path="/inventorydetails">
<InventoryDetails />
</Route>
<Route path="/items/add">
<ItemForm type="POST" />
</Route>
<Route path="/users/add">
<AddFields field="/users" data={{}} type="POST" />
</Route>
<Route path="/suppliers/add">
<AddFields field="/suppliers" data={{}} type="POST" />
</Route>
<Route path="/fields/add">
<AddFields field="/fields" data={{}} type="POST" />
</Route>
<Route path="/projects/add">
<AddFields field="/projects" data={{}} type="POST" />
</Route>
<Route path="/generatepo/add">
<AddMaterialForm field="/generatepo" data={{}} type="POST" />
</Route>
<Route path="/inventoryheader/add">
<AddIntentTable field="/inventoryheader" data={{}} type="POST" />
</Route>
<Route path="/items/edit/:ID">
<ItemForm type="PUT" />
</Route>
<Route path="/users/edit/:ID">
<AddFields field="/users" data={props.user} type="PUT" />
</Route>
<Route path="/suppliers/edit/:ID">
<AddFields field="/suppliers" data={props.supplier} type="PUT" />
</Route>
<Route path="/fields/edit/:ID">
<AddFields field="/fields" data={props.field} type="PUT" />
</Route>
<Route path="/projects/edit/:ID">
<AddFields field="/projects" data={props.project} type="PUT" />
</Route>
<Route exact path="/inventory/edit">
<InventoryHeader />
</Route>
<Route path="/purchase/edit">
<GeneratePO />
</Route>
<Route path="/generatepo/edit/:ID">
<AddMaterialForm
field="/generatepo"
data={props.materialForm}
type="PUT"
/>
</Route>
<Route path="/inventoryheader/edit/:ID">
<AddIntentTable
field="/inventoryheader"
data={props.inventoryTable}
type="PUT"
/>
</Route>
<Route path="/items/view/:ID">
<ViewItems field="/items" data={props.item} />
</Route>
<Route path="/users/view/:ID">
<ViewItems field="/users" data={props.user} />
</Route>
<Route path="/suppliers/view/:ID">
<ViewItems field="/suppliers" data={props.supplier} />
</Route>
<Route path="/fields/view/:ID">
<ViewItems field="/fields" data={props.field} />
</Route>
<Route path="/projects/view/:ID">
<ViewItems field="/projects" data={props.project} />
</Route>
<Route path="/generatepo/view/:ID">
<ViewMaterialFormItem
field="/generatepo"
data={props.materialForm}
/>
</Route>
<Route path="/inventoryheader/view/:ID">
<ViewItems field="/inventoryheader" data={props.inventoryTable} />
</Route>
<Route path="/inventoryissues">
<InventoryIssues />
</Route>
<Route path="/inventoryindents">
<InventoryIndents />
</Route>
<Route path="/podetails">
<PODetails />
</Route>
<Route path="/poreport">
<POReport />
</Route>
</Switch>
</Router>
</React.Fragment>
);
}
const mapStateToProps = (state) => ({
item: state.Items.fields,
field: state.Fields.fields,
project: state.Projects.fields,
supplier: state.Suppliers.fields,
user: state.Users.fields,
materialForm: state.MaterialForm.fields,
inventoryTable: state.InventoryTable.fields,
});
export default connect(mapStateToProps, null)(Routers);
table.js file:
This is a reusable component that most of the files use dynamicly.
import React, { useState, useEffect } from "react";
import { makeStyles } from "#material-ui/core/styles";
import Table from "#material-ui/core/Table";
import TableBody from "#material-ui/core/TableBody";
import TableCell from "#material-ui/core/TableCell";
import TableContainer from "#material-ui/core/TableContainer";
import TableHead from "#material-ui/core/TableHead";
import TableRow from "#material-ui/core/TableRow";
import Paper from "#material-ui/core/Paper";
import Button from "#material-ui/core/Button";
import VisibilityIcon from "#material-ui/icons/Visibility";
import EditIcon from "#material-ui/icons/Edit";
import DeleteIcon from "#material-ui/icons/Delete";
import { BottomScrollListener } from "react-bottom-scroll-listener";
import { connect } from "react-redux";
import { loadFields, removeFields } from "../store/actions/actionCreators";
import { useLocation, useHistory } from "react-router-dom";
const useStyles = makeStyles({
table: {
minWidth: 650,
},
});
function BasicTable(props) {
const location = useLocation();
const history = useHistory();
const [items, setItems] = useState([...props.body]);
const [limit, setLimit] = useState(20);
const classes = useStyles();
useEffect(() => {
const interval = setInterval(() => setItems([...props.body]), 500);
return () => {
clearInterval(interval);
};
}, [limit, props.body]);
const handleDelete = (data) => {
props.removeFields(location.pathname, data);
setItems(items.filter((item) => item.id !== data.id));
props.reRender();
};
const handleEdit = (id) => {
history.push(`${location.pathname}/edit/${id}`);
};
const handleView = (id) => {
history.push(`${location.pathname}/view/${id}`);
};
const handleScroll = () => {
// setItems([
// ...items,
// ...props.body.slice(
// limit,
// props.body.length > limit + 20 ? limit + 20 : props.body.length
// ),
// ]);
// setLimit(limit + 20);
};
const tableHeader = props.header.map((item, index) => {
if (index === 0) {
return (
<TableCell key={item}>
<b>{item}</b>
</TableCell>
);
} else {
return (
<TableCell key={item} align="right">
<b>{item}</b>
</TableCell>
);
}
});
const tableContent = items.map((item, index) => {
return (
<TableRow key={index}>
{Object.values(item).map((row, ind) =>
ind === 0 ? (
<TableCell key={ind} component="th" scope="row">
{row}
</TableCell>
) : typeof row === "object" ? (
String(row.name ? row.name : null)
) : (
<TableCell key={ind} align="right">
{location.pathname === "/users" && ind === 3 ? "**********" : row}
</TableCell>
)
)}
{location.pathname === "/inventoryindents" ? (
<Button variant="outlined" color="primary">
Open Indent
</Button>
) : (
<TableCell align="right">
{/* <VisibilityIcon
style={{ margin: "5px", cursor: "pointer" }}
onClick={() => handleView(item.id)}
/> */}
<EditIcon
onClick={() => handleEdit(item.id)}
style={{ margin: "5px", cursor: "pointer" }}
/>
<DeleteIcon
onClick={() => handleDelete(item)}
style={{ margin: "5px", cursor: "pointer" }}
/>
</TableCell>
)}
</TableRow>
);
});
return (
<BottomScrollListener onBottom={() => handleScroll()}>
<TableContainer component={Paper}>
<Table className={classes.table} aria-label="simple table">
<TableHead>
<TableRow>
{tableHeader}
<TableCell align="right">
<b>Actions</b>
</TableCell>
</TableRow>
</TableHead>
<TableBody>{tableContent}</TableBody>
</Table>
</TableContainer>
<br />
<br />
<br />
</BottomScrollListener>
);
}
const mapStateToProps = (state) => ({
state,
});
export default connect(mapStateToProps, { loadFields, removeFields })(
BasicTable
);
please help
React components automatically re-render whenever there is a change in their state or props. A simple update of the state, causes all the User Interface (UI) elements to be re-rendered automatically. In your first file, you are making some API call which on success changing the state. Which will tell the react to re-render the component, and again it will do the API and it goes on.
Do all the side effects like API call in useEffect function with proper dependency array.

Categories

Resources