How can i change this code to react redux - reactjs

Here i want to change this code to react redux. How i can change this code using react redux. Kindly provide any solutions for changing this code to react redux using GET method api. As iam new to react js how can i change this code using react redux.
import React from "react";
import { useState, useEffect } from "react";
import { Link } from "react-router-dom";
export default function User() {
const [users, setUsers] = useState([]);
const f = async () => {
const res = await fetch("https://reqres.in/api/userspage=1");
const json = await res.json();
setUsers(json.data);
};
useEffect(() => {
f();
}, []);
const handleLogout = (e) => {
localStorage.clear();
window.location.pathname = "/";
}
return (
<div>
<h1>List Users</h1>
<div>
<button onClick={handleLogout}>Logout</button>
<nav>
<Link to="/Home">Home</Link>
</nav>
<table class="table">
<thead>
<tr>
<th>Id</th>
<th>First_name</th>
<th>Last_name</th>
<th>Email</th>
<th>Avatar</th>
</tr>
</thead>
<tbody>
{users.length &&
users.map((user) => {
return (
<tr>
<td> {user.id}</td>
<td>{user.first_name}</td>
<td> {user.last_name} </td>
<td>{user.email}</td>
<td> <img key={user.avatar} src={user.avatar} alt="avatar" /></td>
</tr>
);
})}
</tbody>
</table>
</div>
</div>
);
}

Related

fetching data not showing in table in react

I am create a table and fetching data using axios but in the table I am not able to print the data when I check data is printing in browser but not able to print the particular data to a table format so what should be change in my code?
import { useEffect, useState } from "react";
import "bootstrap/dist/css/bootstrap.min.css";
import { Table } from "react-bootstrap";
import axios from "axios";
export default function App() {
const [user, setUser] = useState([]);
useEffect(() => {
axios
.get("https://jsonplaceholder.typicode.com/users", (req, res) => {
res.json();
})
.then((data) => setUser({ ...user, data }))
.catch((error) => console.error(error));
});
return (
<div className="App">
<h3 className="text-primary">User List</h3>
<Table
variant="danger"
striped
bordered
hover
className="shadow-lg text-center"
>
<thead>
<tr>
<th>id</th>
<th>Name</th>
<th>UserName</th>
<th>Email</th>
</tr>
</thead>
<tbody>
{user?.data?.length > 0 &&
user.data.map((user) => {
return (
<tr key={user.id}>
<td>{JSON.stringify(user.data["data"].id)}</td>
<td>{JSON.stringify(user.data["data"].name)}</td>
<td>{JSON.stringify(user.data["data"].username)}</td>
<td>{JSON.stringify(user.data["data"].email)}</td>
</tr>
);
})}
</tbody>
</Table>
{/* <div>{JSON.stringify(user.data["data"])}</div> */}
</div>
);
}
for example
import { useEffect, useState } from "react";
import "bootstrap/dist/css/bootstrap.min.css";
import { Table } from "react-bootstrap";
import axios from "axios";
export default function App() {
const [user, setUser] = useState([]);
useEffect(() => {
axios
.get("https://jsonplaceholder.typicode.com/users")
.then((res) => {
setUser(res.data);
})
.catch((error) => console.error(error));
}, []);
return (
<div className="App">
<h3 className="text-primary">User List</h3>
<Table
variant="danger"
striped
bordered
hover
className="shadow-lg text-center"
>
<thead>
<tr>
<th>id</th>
<th>Name</th>
<th>UserName</th>
<th>Email</th>
</tr>
</thead>
<tbody>
{user?.length > 0 &&
user.map((userData) => {
return (
<tr key={userData.id}>
<td>{userData.id}</td>
<td>{userData.name}</td>
<td>{userData.username}</td>
<td>{userData.email}</td>
</tr>
);
})}
</tbody>
</Table>
{/* <div>{JSON.stringify(user)}</div> */}
</div>
);
}
Replace the useEffect code as follow.
useEffect(() => {
axios
.get("https://jsonplaceholder.typicode.com/users")
.then((data) => setUser({ ...user, data }))
.catch((error) => console.error(error));
}, []);
You already know that calling this api will give you an array of users so you can initialise the state as empty array as:
const [users, setUsers] = useState([]);
and when you are using axios then you don't have to use res.json(). axios will do it for you out of the box.
axios
.get("https://jsonplaceholder.typicode.com/users")
.then(({ data }) => setUsers(data))
.catch((error) => console.error(error));
so, after getting data using get method of axios it will return you a promise and you can get data from its data property that is passed an first args. You can directly set state which will be an array of objects.
.then(({ data }) => setUsers(data))
Here I've destructed the object to get only the data property.
Since users will be an array of objects, so you don't have to do any check. You can directly use user.id to get the respective property.
Codesandbox link
export default function App() {
const [users, setUsers] = useState([]);
useEffect(() => {
axios
.get("https://jsonplaceholder.typicode.com/users")
.then(({ data }) => setUsers(data))
.catch((error) => console.error(error));
}, []);
return (
<div className="App">
<h3 className="text-primary">User List</h3>
<Table
variant="danger"
striped
bordered
hover
className="shadow-lg text-center"
>
<thead>
<tr>
<th>id</th>
<th>Name</th>
<th>UserName</th>
<th>Email</th>
</tr>
</thead>
<tbody>
{users.map((user) => {
return (
<tr key={user.id}>
<td>{user.id}</td>
<td>{user.name}</td>
<td>{user.username}</td>
<td>{user.email}</td>
</tr>
);
})}
</tbody>
</Table>
{/* <div>{JSON.stringify(user.data["data"])}</div> */}
</div>
);
}

Is it possible to dipatsch on useSelector function?

Langage used : JS with REACT REDUX
The context : I have a component who render a list of quotes following the user filter and categories choice.
In my filter component, i store the select value (buttonsData), and here i re render a certains component depending on select value.
import React from 'react';
import { Table } from 'react-bootstrap';
import { useSelector } from 'react-redux';
//here each component following the user choice
import { AllForms } from './categories/AllForms';
import { AtoZ } from './sorted/AtoZ';
import { ZtoA } from './sorted/ZtoA';
import { Ascend } from './sorted/Ascend';
import CurrentOffers from './categories/CurrentOffers';
import ValidateOffers from './categories/ValidateOffers';
export const OfferList = () => {
const buttonsData = useSelector((state) => state.buttonReducer);
return (
<Table hover responsive="md" className="folder__table">
<thead className="folder__content">
<tr className="folder__titles">
<th className="folder__title"> </th>
<th className="folder__title">Order REF</th>
<th
className="folder__title"
>
Entité
</th>
<th className="folder__title">Customer</th>
<th className="folder__title">Status</th>
<th className="folder__title">Date</th>
<th className="folder__title "> </th>
</tr>
</thead>
{buttonsData.activeComponent === 'AllForms' && <AllForms />}
{buttonsData.activeComponent === 'Ascend' && <Ascend />}
{buttonsData.activeComponent === 'validate' && <ValidateOffers />}
</Table>
);
};
I have used createSelector to filter and sort my datas (working fine).
import { useSelector } from 'react-redux';
export const SelectOffersValidate = () => {
//here i select ALL my forms, get with axios
const formsDatas = useSelector((state) => state.offersReducer);
const sortedForms = [...formsDatas].filter(
(oneOffer) => oneOffer.status == 'validate'
);
console.log(sortedForms);
return sortedForms;
};
export const SelectOffersAscend = () => {
const formsDatas = useSelector((state) => state.offersReducer);
const sortedForms = [...formsDatas].sort((a, b) =>
b.createdAt.localeCompare(a.createdAt)
);
return sortedForms;
};
Here a component filtered ( i have one component for AllForms, one for Validate and one for ascend, exaclty the same but with own select function)
import React, { useState } from 'react';
import { FiEdit3 } from 'react-icons/fi';
import {
SelectOffersAscend,
} from '../../../selector/projects.selector.js';
import { isEmpty } from '../../../middlewares/verification.js';
import Moment from 'react-moment';
export const Ascend = () => {
const formsAscend = SelectOffersAscend();
return (
<>
<tbody>
{!isEmpty(formsAscend[0]) &&
formsAscend?.map((oneForm) => {
return (
<tr key={oneForm.id}>
<td>
<input
type="checkbox"
/>
</td>
<td>{oneForm.ref} </td>
<td> {oneForm.entity}</td>
<td>{oneForm.customer} </td>
<td>{oneForm.status} </td>
<td>
<Moment format="DD/MM/YYYY" date={oneForm.createdAt} />
</td>
<td>
<FiEdit3 />
</td>
</tr>
);
})}
</tbody>
</>
);
};
My first problem :
I have made a component for EACH filter, but it's repetitive, is there a better way to do ?
The second problem :
"AllForms" and "ValidateOffers" are categories and "Ascend" is a filter.
For the moment i filter only with AllForms but i would like to filtered based on categories choosen.
I've tried to create an action to store the actual categories, so i've tried to dispatch on my createSelector validate function but it's looping so i don't think is the best way to do
SOLUTION : thanks to Chris whol helped me :)
So i have delete all my filtered component to just have one and create a custom hook
import React, { useMemo } from 'react';
import { Table } from 'react-bootstrap';
import { useSelector } from 'react-redux';
import { OfferRows } from './OfferRows';
export const useFilteredOffers = () => {
const buttonsData = useSelector((state) => state.buttonReducer);
const offersData = useSelector((state) => state.offersReducer);
return useMemo(() => {
switch (buttonsData.activeComponent) {
case 'Ascend': // fix casing
return offersData?.sort((a, b) =>
b.createdAt.localeCompare(a.createdAt)
);
case 'validate':
return offersData?.filter((oneOffer) => oneOffer.status === 'validate');
case 'not validate':
return offersData?.filter(
(oneOffer) => oneOffer.status === 'not validate'
);
case 'AtoZ':
return offersData?.sort((a, b) => a.customer.localeCompare(b.customer));
case 'ZtoA':
return offersData?.sort((a, b) => b.customer.localeCompare(a.customer));
default:
return offersData;
}
}, [buttonsData.activeComponent, offersData]);
};
export const OfferList = () => {
const filteredOffers = useFilteredOffers();
return (
<Table hover responsive="md" className="folder__table">
<thead className="folder__content">
<tr className="folder__titles">
<th className="folder__title"> </th>
<th className="folder__title">Order REF</th>
<th className="folder__title">Entité</th>
<th className="folder__title">Customer</th>
<th className="folder__title">Status</th>
<th className="folder__title">Date</th>
<th className="folder__title "> </th>
</tr>
</thead>
<OfferRows offers={filteredOffers} />
</Table>
);
};
Here the rows
import React from 'react';
import { FiEdit3 } from 'react-icons/fi';
import Moment from 'react-moment';
import { isEmpty } from '../../middlewares/verification.js';
export const OfferRows = ({ offers }) => {
return (
<>
<tbody>
{!isEmpty(offers[0]) &&
offers?.map((oneForm) => {
return (
<tr key={oneForm.id}>
<td>
<input type="checkbox" />
</td>
<td>{oneForm.ref} </td>
<td> {oneForm.entity}</td>
<td>{oneForm.customer} </td>
<td>{oneForm.status} </td>
<td>
<Moment format="DD/MM/YYYY" date={oneForm.createdAt} />
</td>
<td>
<FiEdit3 />
</td>
</tr>
);
})}
</tbody>
</>
);
};
I would create a single component for the rendering of the offer rows. The data can be filtered using a single hook that also selects the active filter. You can also pass this down as an argument.
Custom hooks MUST start with the use keyword. See the Rules of Hooks documentation for more information.
const useFilteredOffers = () => {
const activeFilter = useSelector((state) => state.buttonReducer);
const offers = useSelector((state) => state.offersReducer);
return useMemo(() => {
switch (activeFilter) {
case 'Ascend': // fix casing
return offers?.sort((a, b) => b.createdAt.localeCompare(a.createdAt));
case 'validate':
return offers?.filter(oneOffer => oneOffer.status == 'validate');
default:
return offers;
}
}, [activeFilter, offers]);
}
export const OfferList = () => {
const filteredOffers = useFilteredOffers();
return (
<Table hover responsive="md" className="folder__table">
<thead className="folder__content">
<tr className="folder__titles">
<th className="folder__title"> </th>
<th className="folder__title">Order REF</th>
<th
className="folder__title"
>
Entité
</th>
<th className="folder__title">Customer</th>
<th className="folder__title">Status</th>
<th className="folder__title">Date</th>
<th className="folder__title "> </th>
</tr>
</thead>
<OfferRows offers={filteredOffers} />
</Table>
);
};
For completeness, here is the OfferRows component.
PS: You won't need to use the isEmpty validator because Array#map won't have any effect when the Array is empty.
export const OfferRows = (offers) => {
return (
<>
<tbody>
{offers?.map((oneForm) => {
return (
<tr key={oneForm.id}>
<td>
<input
type="checkbox"
/>
</td>
<td>{oneForm.ref} </td>
<td> {oneForm.entity}</td>
<td>{oneForm.customer} </td>
<td>{oneForm.status} </td>
<td>
<Moment format="DD/MM/YYYY" date={oneForm.createdAt} />
</td>
<td>
<FiEdit3 />
</td>
</tr>
);
})}
</tbody>
</>
);
};

How can I fix error when trying to render data?

I'm making an application to render the data in a table dynamically. But this error appears: "getUserData.map is not a function".
I didn't find any apparent errors, how can I solve this problem?
API: link
console: console
useRequestData:
import axios from "axios"
import { useEffect, useState } from "react"
export const useRequestData = (initialState, url) => {
const [data, setData] = useState(initialState)
useEffect(() => {
axios.get(url)
.then((res) => {
setData(res.data)
})
.catch(() => {
alert('Erro')
})
}, [url])
return data
}
Component:
import { Container, TableHeader } from "./styles"
import plusImg from "../../assets/plus.png"
import minusImg from "../../assets/minus.png"
import editImg from "../../assets/edit.png"
import { useRequestData } from "../hooks/useRequestData"
import { baseUrl } from "../../services/api"
export const UsersTable = () => {
const getUserData = useRequestData([], baseUrl)
return (
<Container>
<table>
<thead>
<tr>
<th>
<img src={plusImg} alt="" />
</th>
<th>Nome</th>
<th>Endereço</th>
<th>Cidade</th>
<th>UF</th>
<th>Telefone</th>
<th>E-mail</th>
</tr>
</thead>
<tbody>
{getUserData.map((user) => (
<tr key={user.TECL_ID}>
<tr>
<td>
<img src={minusImg} alt="" />
</td>
<td>
<img src={editImg} alt="" />
</td>
</tr>
<td>{user.TECL_NOME}</td>
<td>{user.TECL_ENDERECO}</td>
<td>{user.TECL_CIDADE}</td>
<td>{user.TECL_UF}</td>
<td>{user.TECL_TELEFONE}</td>
<td>fulano#gmail.com</td>
</tr>
))}
</tbody>
</table>
</Container>
)
}
Few things, inside your custom hook, create a function to get the data outside of the useEffect and THEN, run it inside useEffect.
Now, you have to return your data state from your custom hook in order to use it, so... At the bottom of your custom hook (outside of useEffect) write this:
return { data };
Now in your Component you could do something like this:
const { data } = useRequestData([], baseUrl)
And that's pretty much it, let me know if that helps.

how to react-js-pagination implement with react hook data table

How to integrate pagination code with hooks method data table with. im using react-js-pagination nmp package but there is no one explanation for implement with hook method program.
This my data table code:
import React, { useEffect, useState } from 'react';
import axios from 'axios'
import 'bootstrap/dist/css/bootstrap.min.css';
import {Link} from 'react-router-dom';
const ProTable = () => {
const [data, setData] = useState([]);
useEffect(() => {
loadData();
}, []);
const loadData = async() => {
axios.get('http://localhost:5000/api/clientgetdata')
.then(response => {
setData(response.data.map);
}
const delPro = (item,e) => {
var option = window.confirm(`Are you sure to delete ${e.clientName} OF ${item.projectName}`)
if(option){
const check = axios.delete(`http://localhost:5000/api/clientdelpro/${e.clientName}/${item.projectName}`).then(res => {
//console.log(clientname)
window.location.reload(false)
})
}
}
return (
<>
<div className="row addButton">
<div className="col-lg-1">
<Link
className="btn btn-outline-primary mr-2"
to={'/client/addpro'}
>New</Link>
</div>
<div className="col-lg-1">
{/* <button variant="primary" >Delete</button> */}
</div>
</div>
<div className="row hrtable">
<div className="col-lg-10 col-sm-6 col-md-6">
<div className="table-responsive tcenter" >
<table className="table table-bordered table-hover table-sm">
<thead className="thead-dark">
<tr>
<th scope="col"><input type="checkbox" /></th>
<th scope="col">Client Name</th>
<th scope="col">Project Name</th>
<th scope="col">Status</th>
<th>Action</th>
</tr>
</thead>
{ (data.length > 0) ? data.map( e => {
return (
<>
{e.project.map(item=> {
return (
<tbody>
<tr>
<th scope="row">
<input type="checkbox"/>
</th>
<td><ul>{e.clientName}</ul></td>
<td><ul>{item.projectName}</ul></td>
<td><ul>{item.proStatus}</ul></td>
<td>
<Link
className="btn btn-outline-primary mr-2"
to={`/project/edit/${e.clientName}/${item.projectName}`} >
Edit
</Link>
<button
className="btn btn-danger"
onClick={() => delPro(item,e)}>
Delete
</button>
</td>
</tr>
</tbody>
);
})}
</>
);
}) : <tr><td colSpan="5">No Records Found</td></tr> }
</table>
</div>
</div>
</div>
</>
);
}
export default ProTable;
This is Reaci-js-pagination code.
I am trying to follow this tutorial to create a pagination in my application https://www.npmjs.com/package/react-js-pagination#usage
import React, { Component } from "react";
import ReactDOM from "react-dom";
import Pagination from "react-js-pagination";
require("bootstrap/less/bootstrap.less");
class App extends Component {
constructor(props) {
super(props);
this.state = {
activePage: 15
};
}
handlePageChange(pageNumber) {
console.log(`active page is ${pageNumber}`);
this.setState({activePage: pageNumber});
}
render() {
return (
<div>
<Pagination
activePage={this.state.activePage}
itemsCountPerPage={10}
totalItemsCount={450}
pageRangeDisplayed={5}
onChange={this.handlePageChange.bind(this)}
/>
</div>
);
}
}
plz help me how integrate both code
Try by converting it into hooks
const [state, setState] = React.useState({activePage: 15});
const handlePageChange=(pageNumber) => {
setState({activePage: pageNumber});
// make api call for next page
}
return (
<div>
<Pagination
activePage={state.activePage}
itemsCountPerPage={10} // pass your fixed item per pages
totalItemsCount={450} // total item -> per-page * no of page
pageRangeDisplayed={5}
onChange={handlePageChange}
/>
</div>
);

How can I pass props to another components with in reactjs

I'm trying to pass product data from AllProducts component to Product component.
AllProducts.jsx: is showing all the products I have and Product.jsx will show specific product and how can I pass data to Product.jsx?
Here is my AllProducts.jsx:
const AllProducts = (props) => {
const [products, setProducts] = useState([]);
const getProductsAPI = () => {
axios
.get("http://localhost:8000/api/products")
.then((res) => {
setProducts(res.data);
getProductsAPI();
})
.catch((err) => {
console.log(err);
});
};
useEffect(() => {
getProductsAPI();
}, [props]);
return (
<div>
<table className="table table-bordered table-hover">
<thead>
<tr>
<th>#</th>
<th>Title</th>
<th>Action</th>
</tr>
</thead>
<tbody>
{products.map((product, i) => (
<tr key={i}>
<th scope="row">{i}</th>
<td>{product.title}</td>
<td>
<Link to={`/products/${product._id}`}> View </Link>
</td>
</tr>
))}
</tbody>
</table>
</div>
);
};
and here is my Product.jsx:
const Product = (props) => {
return (
<div className="container">
<h4>{props.product.title}</h4>
</div>
);
};
export default Product;
Here is my project github if you want to look at all the code I have: https://github.com/nathannewyen/full-mern/tree/master/product-manager
If the data is fully loaded for each product in AllProducts, and you don't want to make another API call by product id in the Product component, in this case, you don't have to use a route link to view Product, just make a conditional rendering to show Product component inside AllProducts component. pseudo-code as below,
const [showProduct, setShowProduct] = useState(false);
const [currentProduct, setCurrentProduct] = useState();
const showProduct = (product) => {
setShowProduct(true);
setCurrentProduct(product);
}
<tbody>
{products.map((product, i) => (
<tr key={i}>
<th scope="row">{i}</th>
<td>{product.title}</td>
<td>
<button type="button" onclick = {showProduct(product)}>View</button>
</td>
</tr>
))}
</tbody>
return (showProduct ? <Product /> : <AllProucts/>)
If you also need to make another API call to get extra data for each product, then use the router link but perhaps you can not pass props.

Resources