Array of object is getting undefined - reactjs

This is my Cart.jsx
import { createContext, useEffect } from "react"
import Cake from "../About Section/Cake";
const PdtList = createContext();
export default function Cart() {
let list = [
{
id: "52",
name: "Doll cake"
// images: image80
},
{
id: "53",
name: "Mixed Platte cake"
// images: image81
},
{
id: "54",
name: "Pinata cake"
// images: image82
},
{
id: "55",
name: "Bomb cake"
// images: image83
}
];
return (
<>
<main className="align" >
<h1>Thanks for shopping with us</h1>
<PdtList.Provider value={list}>
<Cake />
</PdtList.Provider>
</main>
</>
)
}
export { PdtList };
This is the Cake.jsx
import { PdtList } from "../Cart/Cart";
import { useContext, useState, useEffect } from "react";
export default function Cake(props) {
const { name, images, bold, cut } = props;
const list = useContext(PdtList);
console.log(list);
console.log(typeof(list));
const Add_Products = (index) => {
console.log('Add_Products called');
let tobeAdded = { name, images, bold };
};
return (
<>
<main className="align unique">
<img src={images} alt="" />
<h1>{name}</h1>
<div className="align2">
<small>Rs {bold}</small>
<small style={{ margin: "0px 10px" }}></small>
<small
style={{ "fontSize": "15px", textDecoration: "line-through" }}
>
Rs {cut}
</small>
</div>
<button onClick={Add_Products} style={{ margin: "10px 0px" }}>
Click here
</button>
</main>
</>
);
}
This is the console,
When I am trying to console the list in the Add_Products function in the Cake.jsx then I am getting undefined.
This is a working codesandbox Link
This is the Birthday.jsx
import image60 from './assets/cake60.jpeg'
import image61 from './assets/cake61.jpeg'
import image62 from './assets/cake62.jpeg'
import image63 from './assets/cake63.jpeg'
import image64 from './assets/cake64.jpeg'
import image65 from './assets/cake65.jpeg'
import image66 from './assets/cake66.jpeg'
import image67 from './assets/cake67.jpeg'
import image68 from './assets/cake68.jpeg'
import image69 from './assets/cake69.jpeg'
import Cake from './Cake'
import { useContext } from "react"
import { PdtList } from "../Cart/Cart"
const pdtArray = [{
id: '32',
name: "Anniversary cake",
images: image60
},
{
id: '33',
name: "Anniversary cake",
images: image61
},
{
id: '134',
name: "Anniversary cake",
images: image62
},
{
id: '34',
name: "Anniversary cake",
images: image63
},
{
id: '35',
name: "Anniversary cake",
images: image64
},
{
id: '36',
name: "Anniversary cake",
images: image65
},
{
id: '37',
name: "Anniversary cake",
images: image66
},
{
id: '38',
name: "Anniversary cake",
images: image67
},
{
id: '39',
name: "Anniversary cake",
images: image68
},
{
id: '40',
name: "Anniversary cake",
images: image69
},]
export default function Birthday(props) {
const list = useContext(PdtList);
console.log(list);
const { title } = props;
return (
<>
<main className='PDT_heading align' >
<h1>{title}</h1>
<div className="grid_system">
{
pdtArray.map((e) => {
const { name, images, id } = e;
return (
<Cake key={id} name={name} images={images} cut="232" bold="343" />
)
})
}
</div>
</main>
</>
)
}

When you are going to use the useContext in a component, make sure that component is wrapped inside the Context.Provider (either the component or the parent of the component). Only then the useContext can able to access the values of the context else it will return the default value which is undefined.
So, the root component will be something lie:
<StrictMode>
<PdtList.Provider value={list}>
<Cart />
<Birthday />
</PdtList.Provider>
</StrictMode>
I wrapped the components inside the Provider so all the components inside can able to access the value.
working link: link

Related

importing the library into the header in loop

I have two sepearte file:
page.js
import React from 'react';
import 'tailwindcss/tailwind.css';
import { MenuModalData } from './data';
d
export default function App() {
return (
<>
{Object.entries(MenuModalData).map(([key, value]) => {
return (
<>
<div>
{value?.icon && <value.icon size="1.6rem" className="my-auto" />}
</div>
</>
)
})}
</>
)
}
data.js
export const MenuModalData = [
{
type: "menu",
name: "Products",
page: "/shop",
},
{
type: "menu",
name: "Contact",
icon: "BiChat",
page: "/shop",
}
]
How I can import react-icons BiChat by lines similar with import to header in file?
{value?.icon && <value.icon size="1.6rem" className="my-auto" />}
p.s
interactive version on stackblitz
You can import your icon in your data.js file like this :
import { BiChat } from "react-icons/bi";
export const MenuModalData = [
{
type: "menu",
name: "Products",
page: "/shop"
},
{
type: "menu",
name: "Contact",
icon: BiChat,
page: "/shop"
}
];
By the way you can replace
Object.entries(MenuModalData).map(([key, value]) => {
by :
MenuModalData.map((value) => {

How to show FAQs with multiple categories using React FAQ Component

I am trying to create FAQ page in my react project using below package:
https://www.npmjs.com/package/react-faq-component
I am able to show FAQ with 1 category.
I want to show questions/answers with different categories:
Code:
import React, { useState } from 'react';
import FaqData from 'react-faq-component';
function Faq() {
const [rows, setRowsOption] = useState(null);
const data = {
title: 'FAQ (how it works)',
rows: [
{
title: 'How do I change my password?',
content: `Answer here.`,
},
{
title: 'How do I sign up?',
content:'Answer here.',
},
],
};
return (
<div>
<h2 className="section-title">My FAQ&apos;s</h2>
<div className="faq-style-wrapper">
<FaqData data={data} getRowOptions={setRowsOption} />
</div>
</div>
);
}
If any other demo/library can give me desired output, please suggest those as well.
As suggested by #Arkellys I have used one component per category & its worked for me. Thanks again #Arkellys.
I am adding answer below for more details:
import React, { useState } from 'react';
import FaqData from 'react-faq-component';
function Faq() {
const [rows, setRowsOption] = useState(null);
const data1 = {
title: 'FAQ (how it works)',
rows: [
{
title: 'How do I change my password?',
content: `Answer here.`,
},
{
title: 'How do I sign up?',
content:'Answer here.',
},
],
};
const data2 = {
title: 'FAQ (how it works)',
rows: [
{
title: 'How do I change my password?',
content: `Answer here.`,
},
{
title: 'How do I sign up?',
content:'Answer here.',
},
],
};
const data3 = {
title: 'FAQ (how it works)',
rows: [
{
title: 'How do I change my password?',
content: `Answer here.`,
},
{
title: 'How do I sign up?',
content:'Answer here.',
},
],
};
return (
<div>
<h2 className="section-title">My FAQ&apos;s</h2>
<div className="faq-style-wrapper">
<FaqData data={data1} getRowOptions={setRowsOption} />
<FaqData data={data2} getRowOptions={setRowsOption} />
<FaqData data={data3} getRowOptions={setRowsOption} />
</div>
</div>
);
}

React.js: Customize sidebar menu based on API response

I'm trying to customize the sidebar navigation menu of my app based on a JSON response
The concept I'm trying to pattern my code to is using React Context and React Hooks
From my Header.js (which is my top navigation)
import {
useUserDispatch,
customizeSidebar
} from "../../context/UserContext";
var userDispatch = useUserDispatch();
useEffect(() => {
if( selectedProduct.trim() == "remittance" ){
setIsRemLabelHidden(true)
} else if( selectedProduct == "inward" ){
customizeSidebar(userDispatch, "91454020-C1AC-446C-A1CA-C68F6FDBB053", props.history)
setIsRemLabelHidden(false)
}
}, [selectedProduct]);
I trigger customizeSidebar function which is found in my UserContext.js
export {
UserProvider,
useUserState,
useUserDispatch,
customizeSidebar,
};
function customizeSidebar(dispatch, profileId, history){
ProfileMaintenanceService.retrieveProfileDetails(profileId)
.then((response) => {
console.log("customizeSidebar response.data ", response.data)
}).catch((err) => {
// check first if api is down
console.log("customizeSidebar - catch err.response.data >>> ", err.response.data)
})
}
As seen above, I can now get the JSON response in the then statement.
My question would be, how do I pass the JSON response, for instance I saved it in a state. How do I pass it to other component?
Specifically in my Sidebar.js
import React, { useState, useEffect } from "react";
import { Drawer, IconButton, List } from "#material-ui/core";
import {
SwapHoriz as SwapHorizIcon,
Inbox as InboxIcon,
PresentToAll as PresentToAllIcon,
Help as HelpIcon,
ListAlt as ListAltIcon,
Language as LanguageIcon,
Description as DescriptionIcon,
List as ListIcon,
Money as MoneyIcon,
Face as FaceIcon,
TransferWithinAStation as TransferWithinAStationIcon,
AttachMoney as AttachMoneyIcon,
PersonPinCircle as PersonPinCircleIcon,
Home as HomeIcon,
ArrowBack as ArrowBackIcon,
Edit as EditIcon
} from "#material-ui/icons";
import { useTheme } from "#material-ui/styles";
import { withRouter } from "react-router-dom";
import classNames from "classnames";
import useStyles from "./styles";
import SidebarLink from "./components/SidebarLink/SidebarLink";
import {
useLayoutState,
useLayoutDispatch,
toggleSidebar
} from "../../context/LayoutContext";
import Dot from "./components/Dot";
function Sidebar({ location }) {
var classes = useStyles();
var theme = useTheme();
var { isSidebarOpened } = useLayoutState();
var layoutDispatch = useLayoutDispatch();
var [isPermanent, setPermanent] = useState(true);
var structure = [
{ id: 0,
label: "Dashboard",
link: "/app/dashboard",
icon: <HomeIcon /> },
{
id: 1,
label: "Inward",
link: "/app/inward",
icon: <InboxIcon />,
children: [
{ label: "PESONet", link: "/app/inward/pesonet", icon: <Dot size="small" color="primary" /> },
{ label: "PESONet Inquiry", link: "/app/inward/pesonetinquiry", icon: <Dot size="small" color="primary" /> },
{ label: "PDDTS", link: "/app/inward/pddts", icon: <Dot size="small" color="primary" /> },
// { label: "PDDTS Inquiry", link: "/app/inward/pddtsinquiry" },
{ label: "SWIFT", link: "/app/inward/swift", icon: <Dot size="small" color="primary" /> },
// { label: "SWIFT Inquiry", link: "/app/inward/swiftinquiry" },
{ label: "Philpass", link: "/app/inward/philpass", icon: <Dot size="small" color="primary" /> },
],
},
// {
// id: 2,
// label: "Outward",
// link: "/app/outward",
// icon: <PresentToAllIcon />,
// children: [
// { label: "Inward", link: "/app/transfers/inward", icon: <InboxIcon /> },
// { label: "Outward", link: "/app/transfers/outward", icon: <PresentToAllIcon /> },
// ],
// },
{ id: 3, type: "divider" },
{
id: 4,
label: "Proof List",
link: "/app/prooflist",
icon: <ListAltIcon />,
children: [
{ label: "Proof Web", link: "/app/prooflist/web", icon: <LanguageIcon /> },
{ label: "Proof Others", link: "/app/prooflist/others", icon: <ListIcon /> },
],
},
{ id: 5, label: "Miscellaneous", link: "/app/misc", icon: <DescriptionIcon /> },
{
id: 6,
label: "RPS",
link: "/app/rps",
icon: <MoneyIcon />,
children: [
{ label: "Client Maintenance", link: "/app/rps/clientmaintenance", icon: <FaceIcon /> },
{ label: "Process SFTP", link: "/app/rps/sftp", icon: <TransferWithinAStationIcon /> },
{ label: "Process PESONet", link: "/app/rps/pesonet", icon: <AttachMoneyIcon /> },
{ label: "Override Enrollment", link: "/app/rps/overrideenrollment", icon: <PersonPinCircleIcon /> },
],
},
{ id: 7, label: "Message Converter", link: "/app/message", icon: <EditIcon /> },
];
useEffect(function() {
window.addEventListener("resize", handleWindowWidthChange);
handleWindowWidthChange();
return function cleanup() {
window.removeEventListener("resize", handleWindowWidthChange);
};
});
return (
<Drawer
variant={isPermanent ? "permanent" : "temporary"}
className={classNames(classes.drawer, {
[classes.drawerOpen]: isSidebarOpened,
[classes.drawerClose]: !isSidebarOpened,
})}
classes={{
paper: classNames({
[classes.drawerOpen]: isSidebarOpened,
[classes.drawerClose]: !isSidebarOpened,
}),
}}
open={isSidebarOpened}
>
<div className={classes.toolbar} />
<div className={classes.mobileBackButton}>
<IconButton onClick={() => toggleSidebar(layoutDispatch)}>
<ArrowBackIcon
classes={{
root: classNames(classes.headerIcon, classes.headerIconCollapse),
}}
/>
</IconButton>
</div>
<List className={classes.sidebarList}>
{structure.map(link => (
<SidebarLink
key={link.id}
location={location}
isSidebarOpened={isSidebarOpened}
{...link}
/>
))}
</List>
</Drawer>
);
function handleWindowWidthChange() {
var windowWidth = window.innerWidth;
var breakpointWidth = theme.breakpoints.values.md;
var isSmallScreen = windowWidth < breakpointWidth;
if (isSmallScreen && isPermanent) {
setPermanent(false);
} else if (!isSmallScreen && !isPermanent) {
setPermanent(true);
}
}
}
export default withRouter(Sidebar);
Also, should I save the json data on the state? Or on the context. If on the context, how?
Thanks in advance for those who would help.
Try this
use state. Make the customizeSidebar return the response, and call this kind of code in your SideBar component :
const [sideBar, setSideBar] = useState({})
useEffect(() => {
const sidebar = customizeSidebar()
setSideBar(sidebar)
}, [])
then below the code call your sidebar using the sideBar state, the sideBar will re-render with the new sidebar responded.
also maybe you want to put a loading animation while waiting for the sidebar result. I don't get the idea why you need to put it in context but the solution should works IMO.

How to add SrNo (#) column at first position at mui-datatable React.js

Created table using React and MUI-Datatables: need to add SrNo column at first, also need to add Delete and IsActive button.
import React, { useState, useEffect } from 'react';
import Grid from '#material-ui/core/Grid';
import Switch from '#material-ui/core/Switch';
import MUIDataTable from "mui-datatables";
export const Services = () => {
const [itemList, setItemList] = useState([]);
const [mainColumns, setMainColumns] = useState([]);
const selectData = async () => {
const response = await ServiceAPI(); // data from web wervice
var data = JSON.parse(response.data);
setItemList(data);
};
const createColumns = () => {
var columns = [];
// how to add Sr No column
columns.push(
{
label: 'ID',
name: 'service_id',
});
columns.push(
{
label: 'Name',
name: 'service_name',
});
setMainColumns(columns);
};
useEffect(() => {
createColumns();
selectData();
}, []);
return (
<>
<h3>Service</h3>
<Grid container >
<Grid item xs={12}>
<MUIDataTable
title={"Service"}
data={itemList}
columns={mainColumns}
className="table nowrap"
/>
</Grid>
</Grid>
</>
);
}
tried below code for active/deactivate, but OnChange() is run every time, which should call on only click event (also tried OnClick()):
columns.push(
{
label: 'Active',
name: 'is_active',
options: {
filter: false,
sort: false,
customBodyRender: (value, tableMeta, updateValue) => {
const serviceID = tableMeta.rowData[0];
return (
<Switch color="primary" checked={value} value={value} onChange={activate}/>
/>
);
}
}
});
Please check example. I have added serial number and delete button in this example.
import React from "react";
import ReactDOM from "react-dom";
import MUIDataTable from "mui-datatables";
import IconButton from "#material-ui/core/IconButton";
import Button from "#material-ui/core/Button";
export default class MuiDatatableSerial extends React.Component {
render() {
const columns = [
{name: "sl", label: "Serial No"},
{name: "name", label: "Name"},
{name: "title", label: "Title"},
{name: "location", label: "Location"},
{name: "age", label: "Age"},
{name: "salary", label: "Salary"},
{
name: "delete",
label: "",
options: {
filter: false,
sort: false,
customBodyRender: (value, tableMeta, updateValue) => {
return <Button
color="secondary"
onClick={(ev) =>
alert('deleted')
}> Delete
</Button>;
},
}
}
];
const data = [
{name: "Khabir Uddin", title: "Senior Software Engineer", location: "Dhaka", age: 38, salary: "$150,000"},
{name: "Gabby George", title: "Business Analyst", location: "Minneapolis", age: 30, salary: "$100,000"},
{name: "Aiden Lloyd", title: "Business Consultant", location: "Dallas", age: 55, salary: "$200,000"}
];
let newData = [];
data.map((item, index) => {
newData.push({sl: index + 1, ...item});
});
const options = {
selectableRows: "none",
onRowsSelect: (rowsSelected, allRows) => {
},
};
return (
<MUIDataTable
title={"ACME Employee list"}
data={newData}
columns={columns}
options={options}
/>
);
}
}

How to rewrite styles of #devexpress/dx-react-grid-material-ui?

Is there any way to rewrite styles of TableSummaryRow from '#devexpress/dx-react-grid-material-ui' library?
What I have: a component which renders table (using '#devexpress/dx-react-grid-material-ui' library) and in the last row outputs the total number of rows in the table.
What I need to do: style table cell in which TableSummaryRow renders result.
I already tried this solution, but it don't work for me.
Here is simpifide code of my component:
import React from 'react';
import { SummaryState } from '#devexpress/dx-react-grid';
import {
TableHeaderRow,
TableSummaryRow
} from '#devexpress/dx-react-grid-material-ui';
import { ExtendedGrid } from 'components/DxGrid/index';
const Table = ({ rows }) => (
<ExtendedGrid rows={rows} columns={reportColumns}>
<SummaryState totalItems={[{ columnName: 'userName', type: 'count' }]} />
<TableHeaderRow />
<TableSummaryRow messages={{ count: 'Number of rows' }} />
</ExtendedGrid>
);
export default Table;
I figured out this by myself, maybe it will be useful for somebody.
This official docs page helped me. So I used makeStyles method.
Here is working DEMO.
And the final component (based on Andrei Konstantinov's answer) code:
import React from "react";
import { render } from "react-dom";
import Paper from "#material-ui/core/Paper";
import { makeStyles } from "#material-ui/styles";
import { SummaryState, IntegratedSummary } from "#devexpress/dx-react-grid";
import {
Grid,
Table,
TableHeaderRow,
TableSummaryRow
} from "#devexpress/dx-react-grid-material-ui";
const useStyles = makeStyles({
root: {
"& tfoot": {
"& td": {
background: "linear-gradient(45deg, #FE6B8B 30%, #FF8E53 90%)",
"&:empty": {
background: "none"
}
}
}
}
});
const Hook = () => {
const data = {
totalSummaryItems: [{ columnName: "weight", type: "sum" }],
columns: [
{ name: "name", title: "Name" },
{ name: "weight", title: "Weight" }
],
rows: [
{ name: "Sandra", weight: 123 },
{ name: "Andy", weight: 9000 },
{ name: "Einstein", weight: 56 },
{ name: "Bob", weight: 11 }
]
};
const { rows, columns } = data;
const classes = useStyles();
return (
<Paper className={classes.root}>
<Grid rows={rows} columns={columns}>
<SummaryState totalItems={data.totalSummaryItems} />
<IntegratedSummary />
<Table />
<TableHeaderRow />
<TableSummaryRow messages={{ sum: "Total weight of the group" }} />
</Grid>
</Paper>
);
};
render(<Hook />, document.getElementById("root"));
According to TableSumRow's docs you need to use SummaryState component.
Also, for some reason, I can't make it work without IntegratedSummary component as well, even if it's marked as optional.
You can find working demo here.
And here is a code from demo. There is a total weight row for the whole team.
import React from "react";
import { render } from "react-dom";
import { SummaryState, IntegratedSummary } from "#devexpress/dx-react-grid";
import {
Grid,
Table,
TableHeaderRow,
TableSummaryRow
} from "#devexpress/dx-react-grid-material-ui";
class App extends React.PureComponent {
constructor(props) {
super(props);
this.state = {
totalSummaryItems: [{ columnName: "weight", type: "sum" }],
columns: [
{ name: "name", title: "Name" },
{ name: "weight", title: "Weight" }
],
rows: [
{ name: "Sandra", weight: 123 },
{ name: "Andy", weight: 9000 },
{ name: "Einstein", weight: 56 },
{ name: "Bob", weight: 11 }
]
};
}
render() {
const { rows, columns } = this.state;
return (
<Grid rows={rows} columns={columns}>
<SummaryState totalItems={this.state.totalSummaryItems} />
<IntegratedSummary />
<Table />
<TableHeaderRow />
<TableSummaryRow messages={{ sum: "Total weight of the group" }} />
</Grid>
</Paper>
);
}
}
render(<App />, document.getElementById("root"));

Resources