How to create multiple layouts in Next js? - reactjs

I want to create another layout on my nextjs app. I saw this method somewhere, on adding multiple/nested layout in next js. The problem is I can't make this work, there's always this error:
Error: MyApp(...): Nothing was returned from render. This usually means a return statement is missing. Or, to render nothing, return null.
Now this is my code:
My _app.js
import Layout from "./../components/Layout";
function MyApp({ Component, pageProps }) {
const getLayout = Component.pageLayout || ((page) => <Layout>{page}</Layout>);
return getLayout(<Component {...pageProps} />);
}
export default MyApp;
This is my Layout
import React, { Fragment, useState, useEffect, useRef } from "react";
import { useRouter } from 'next/router';
import NavBar from "./../NavBar";
import MidNavBar from "./../MidNavBar";
import Banner from "./../Banner";
const Layout = ({ children, navBarRefProps }) => {
const navBarRef = useRef();
const router = useRouter();
const navBarRefPropsHandle = (props) => {
navBarRef.current = props.current;
navBarRefProps(navBarRef.current);
}
return(
<Fragment>
<div className="wrapper">
<NavBar navBarRefProps={ navBarRefPropsHandle } />
<div className="inner_wrapper">
<Banner/>
{
router.pathname !== "/" ?
<MidNavBar midNavBarRefProps = {midNavBarRefPropsHandle} dummyRefProps={dummyRefPropsHandle}/>
:
""
}
{ children }
</div>
</div>
</Fragment>
)
}
This is my AnotherLayout
const AnotherLayout = ({ children }) => {
return(
<Fragment>
<main>
<div>
<aside className="menu">
<div className="menu_header">
<div className="menu_title">
<span>
Panel
</span>
<button onClick={logoutHandle}>
logout
</button>
</div>
<button className="burger" onClick={openMenuHandle}>
<div className="burger-one">
</div>
<div className="burger-two">
</div>
<div className="burger-three">
</div>
</button>
</div>
<div ref={menuBodyRef} className="menu_body">
<ul>
<li>
<Link href={ url + "/rooms" }>
<div>
</div>
News
</Link>
</li>
<li>
<Link href={ url + "/events" }>
<div>
</div>
Events
</Link>
</li>
<li>
<Link href={ url + "/categories" }>
<div>
<i className="fas fa-snowboarding"></i>
</div>
Activities
</Link>
</li>
</ul>
</div>
</aside>
<section className="container_panel">
{ children }
</section>
</div>
</main>
</Fragment>
)
}
export default AnotherLayout;
And this is my index page
import React, { Fragment, useState, useEffect, useRef } from "react";
import AnotherLayout from "./../../../../components/AnotherLayout";
const Panel = () => {
// a lot of codes here.....
return(
<Fragment>
<section>
<div>
<div>
<h1><span>Rooms</span> Panel</h1>
</div>
<div className="container_table">
<table>
<thead>
<tr>
<td>Rooms</td>
<td>
<div>
<input type="search" name="search" placeholder="search"/>
</div>
</td>
<td className="col_add">
<button>
add
rooms
</button>
</td>
</tr>
</thead>
<tbody>
{
rooms.map(room => {
return(
<tr key={room._id}>
<td colSpan="2">
<button>{room.title}</button>
</td>
<td className="ud">
<button className="edit">
edit
</button>
<button className="delete">
delete
</button>
</td>
</tr>
)
})
}
</tbody>
<tfoot>
<tr>
<td>
</td>
</tr>
</tfoot>
</table>
</div>
</div>
</section>
</Fragment>
)
}
Panel.getLayout = (page) => {
<AdminLayout>
{ page }
</AdminLayout>
}
export default Panel;
Thank you!.

Solved this by adding return()
Panel.getLayout = (page) => {
return(
<AdminLayout>
{ page }
</AdminLayout>
)
}

Related

How to pass partial data to a parent component in react

I have the following Component TBorrowed
import React, { Fragment, useState} from "react";
import {Link} from 'react-router-dom';
const EditItem = ({ item }) => {
const [name, setName] = useState(item.name)
const saveData = async (e) => {
e.preventDefault();
const body = { name}
await fetch(`http://127.0.0.1:5000/item/edit/${item.id}`, {
method: "PUT",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(body)
})
}
return (
<Fragment>
<Link className="link" data-toggle="modal" data-target={`#id${item.id}`} >{item.name}</Link>
<div className="modal" id={`id${item.id}`}>
<div className="modal-dialog">
<div className="modal-content">
<div className="modal-header">
<h4 className="modal-title">Edit Item</h4>
</div>
<div className="modal-body">
<label>Name</label>
<input value={name} onChange={e => { setName(e.target.value) }} type="text" />
</div>
<div className="modal-footer">
<button onClick={e => { saveData(e) }} type="button" className="btn btn-outline-success ml-auto" data-dismiss="modal">Save</button>
</div>
</div>
</div>
</div>
</Fragment>
)
}
export default EditItem;
The above is called in another component, Main as shown below
import React, { useState} from 'react';
import TBorrowed from './TBorrowed';
const Main = () => {
const [items, setItems] = useState([]);
...MANY ITEMS SKIPPED...
return (
<table className="layout">
<thead>
<tr>
<th>#</th>
<th>Name</th>
<th>Code</th>
</tr>
</thead>
<tbody>
{
items.map((item, index) => (
<tr key={item.id}>
<td>{index + 1}</td>
<td>{item.name}</td>
<td>{<TBorrowed item={item} />}</td>
</tr>
))
}
</tbody>
</table>
)
}
export default Main;
The above works well where I am able to see the item code in the Main component's <td></td> when rendered, which when I click, I am able to edit the particular item in a modal.
My issue is I no longer want to edit an item in a modal but I want it rendered on it's own page for editing.
When I try it without a data-toggle = "modal" in the TBorrowed component, I get all the contents of the TBorrowed component displaying in the Main component where the modal is called i.e <td>{<TBorrowed item={item} />}</td>. All the data in TBorrowed is shown in that <td></td> instead of just the item.code as it was showing while using the modal
My code has some parts missing so it can fit here.
Please assist, and if there's more information required I'll provide it.

Page crashes(reading properties of undefined) in React.js

In my project I'm using redux toolkit and react router v6. I have invoices list with 'View' button and when it's clicked it should open page with description about invoice. Also i have add invoice feature. When invoice added and I click on 'View' button page crashes and the error in console say:
Uncaught TypeError: Cannot read properties of undefined (reading 'invoice_num')
And the same happens if i click on existing item and reload the page. It says the error occured in InvoiceItem.js page.
Now the code. InvoiceItem.js
import React from "react";
import { useParams } from "react-router-dom";
import InvoiceItemDescription from "../Invoice/InvoiceItemDescription";
import { INVOICES_LIST } from "./InvoicesList";
const InvoiceItem = () => {
const params = useParams();
const invoice = INVOICES_LIST.find(
(invoice) => invoice.id === params.invoiceId
);
return (
<InvoiceItemDescription
invoiceNumber={invoice.invoice_num}
status={invoice.status}
order_date={invoice.order_date}
bill_from={invoice.bill_from}
bill_from_address={invoice.bill_from_address}
bill_from_email={invoice.bill_from_email}
bill_from_fax={invoice.bill_from_fax}
bill_from_phone={invoice.bill_from_phone}
bill_to={invoice.bill_to}
bill_to_address={invoice.bill_to_address}
bill_to_email={invoice.bill_to_email}
bill_to_fax={invoice.bill_to_fax}
bill_to_phone={invoice.bill_to_phone}
item_name={invoice.ITEMS.item_name}
unit_costs={invoice.ITEMS.unit_costs}
unit={invoice.ITEMS.unit}
price={invoice.ITEMS.price}
/>
);
};
export default InvoiceItem;
InvoiceItemDescription.js file
import React from "react";
import Wrapper from "../../UI/Wrapper";
import Footer from "../../UI/Footer";
import classes from "./InvoiceItemDescription.module.css";
import { Link } from "react-router-dom";
const InvoiceItemDescription = (props) => {
let counter = 1;
return (
<Wrapper isShrinked={props.isShrinked}>
<div className={classes.wrapper}>
<div className={classes["content-wrapper"]}>
<div className={classes["main-wrapper"]}>
<div className={classes["upper-buttons"]}>
<div className={classes["upper-buttons-wrapper"]}>
<Link to="/invoices">
<button type="button" className={classes["go-to-invoices"]}>
Go To Invoices
</button>
</Link>
<Link to="/invoices/edit-invoice">
<button type="button" className={classes["edit-invoice"]}>
Edit Invoice
</button>
</Link>
</div>
</div>
<div className={classes.content}>
<div className={classes["invoice-info"]}>
<div className={classes.info}>
<h3>Invoice Info</h3>
<span>{props.invoiceNumber}</span>
</div>
<div className={classes.order}>
<p>
<span className={classes["order-status"]}>
Order Status:
</span>
<span className={classes.status}>{props.status}</span>
</p>
<p>
<span className={classes["order-date"]}>Order Date:</span>
<span className={classes.date}>{props.order_date}</span>
</p>
</div>
</div>
<div className={classes.bills}>
<div className={classes["bill-from"]}>
<h3>Bill From</h3>
<div>
<p className={classes["bill-from-info"]}>
<span className={classes.name}>{props.bill_from}</span>
<span className={classes.email}>
{props.bill_from_email}
<br></br>
<br></br> {props.bill_from_address}
<br></br>
<br></br>
<br></br> {props.bill_from_phone}
</span>
</p>
</div>
</div>
<div className={classes["bill-to"]}>
<h3>Bill To</h3>
<p className={classes["bill-to-info"]}>
<span className={classes.name}>{props.bill_to}</span>
<span className={classes.email}>
{props.bill_to_email} <br></br>
<br></br> {props.bill_to_address} <br></br>
<br></br>
<br></br>
{props.bill_to_fax} <br></br> {props.bill_to_phone}
</span>
</p>
</div>
</div>
<div className={classes.table}>
<table>
<colgroup>
<col className={classes.col1}></col>
<col className={classes.col2}></col>
<col className={classes.col3}></col>
<col className={classes.col4}></col>
<col className={classes.col5}></col>
</colgroup>
<thead>
<tr>
<td>#</td>
<td>Item Name</td>
<td>Unit Costs</td>
<td>Unit</td>
<td>Price</td>
</tr>
</thead>
<tbody>
<tr>
<td>{counter++}</td>
<td>{props.item_name}</td>
<td>{props.unit_costs}</td>
<td>{props.unit}</td>
<td>{props.price}</td>
</tr>
</tbody>
</table>
</div>
<div className={classes.total}>
<p>
Sub-total:
<span>$13300</span>
</p>
<p>
Vat:
<span>$13300</span>
</p>
<h3>
Grand Total:
<span>$14630</span>
</h3>
</div>
</div>
<div className={classes["lower-btn"]}>
<button type="button">Send Invoice</button>
</div>
</div>
</div>
</div>
<Footer />
</Wrapper>
);
};
export default InvoiceItemDescription;
And Invoice.js file
import React from "react";
import classes from "./Invoice.module.css";
import { useDispatch } from "react-redux";
import { Link } from "react-router-dom";
import { invoiceActions } from "../../store/invoice-slice";
import { FontAwesomeIcon } from "#fortawesome/react-fontawesome";
import { faTrash } from "#fortawesome/free-solid-svg-icons";
const Invoice = (props) => {
const { id, invoice_num, bill_from, bill_to, status } = props.invoiceItem;
const dispatch = useDispatch();
const removeInvoiceItem = () => {
dispatch(invoiceActions.removeInvoice(id));
};
return (
<tr className={classes.height}>
<td>
<span className={classes.checkbox}>
<input type="checkbox"></input>
</span>
</td>
<td>
<span>{invoice_num}</span>
</td>
<td>
<span>{bill_from}</span>
</td>
<td>
<span>{bill_to}</span>
</td>
<td>
<span>14300</span>
{/* This should be a dynamic value later */}
</td>
<td>
<span
className={`${
status === "Pending" ? classes["status-pending"] : ""
} ${status === "Delivered" ? classes["status-delivered"] : ""} ${
status === "Shipped" ? classes["status-shipped"] : ""
}`}
>
{status}
</span>
</td>
<td>
<div className={classes.buttons}>
<Link to={`/invoices/invoice-description/${id}`}>
<button className={classes["view-btn"]}>View</button>
</Link>
<button className={classes["delete-btn"]} onClick={removeInvoiceItem}>
<FontAwesomeIcon icon={faTrash} />
</button>
</div>
</td>
</tr>
);
};
export default Invoice;
I have no idea what can cause the crash of the page. Can someone help me with this, please?
P.S. here is my github repo(it's my PET project) - https://github.com/stepan-slyvka/test-project
The issue is that in the INVOICES_LIST test invoice data exported from src/components/Pages/Invoice/InvoicesList.js you are creating randomly generated id properties. When the page reloads, the entire app reloads, INVOICES_LIST is exported with all new id properties. The id that is read from the URL path is no longer valid and InvoiceItem can't render an invoice object that is undefined.
export const INVOICES_LIST = [
{
id: Math.random().toString(), // <-- random each time app loads
...
},
{
id: Math.random().toString(), // <-- random each time app loads
...
},
{
id: Math.random().toString(), // <-- random each time app loads
...
},
];
You really want GUIDs to be stable, and more determinant and guaranteed for uniqueness, so don't use Math.random to create them, use something more like uuid if you need to generate unique ids.
To resolve your specific issue the fix is to just hardcode a unique id value. Even just complete gibberish, so long as it uniquely identifies an object, is sufficient (for testing).
Example:
export const INVOICES_LIST = [
{
id: '09u34otiuhnrfgp9ioj45',
...
},
{
id: '234098ujh43gikoljaerpgiojaerg',
...
},
{
id: '0934tpinr-9ujw3ensdsf',
...
},
];
In the InvoiceItem component that is searching the INVOICES_LIST array keep in mind that Array.prototype.find potentially returns undefined when no match is found. The UI should handle this. Conditionally render the InvoiceItemDescription only if there is a found invoice.
Example:
const InvoiceItem = () => {
const { invoiceId } = useParams();
const invoice = INVOICES_LIST.find((invoice) => invoice.id === invoiceId);
return invoice ? (
<InvoiceItemDescription
invoice_num={invoice.invoice_num}
status={invoice.status}
order_date={invoice.order_date}
bill_from={invoice.bill_from}
bill_from_address={invoice.bill_from_address}
bill_from_email={invoice.bill_from_email}
bill_from_fax={invoice.bill_from_fax}
bill_from_phone={invoice.bill_from_phone}
bill_to={invoice.bill_to}
bill_to_address={invoice.bill_to_address}
bill_to_email={invoice.bill_to_email}
bill_to_fax={invoice.bill_to_fax}
bill_to_phone={invoice.bill_to_phone}
item_name={invoice.ITEMS.item_name}
unit_costs={invoice.ITEMS.unit_costs}
unit={invoice.ITEMS.unit}
price={invoice.ITEMS.price}
/>
) : (
<div>No Invoices Found.</div>
);
};
So, issue is fixed and to conclude, maybe someone is facing the same problem, I'll write a few words.
Firstly, when you have static data like I had(3 invoices which renders each time page loads) - hardcode your id's.
Secondly, for newly created items use stable id's(example - uuid) and store it somewhere(for example in local storage).
Thirdly, if page crashes or something renders wrong - check your state! In my case issue was in InvoiceItem.js file where i was trying to render INVOICES_LIST instead of selecting my state with const invoices = useSelector((state) => state.invoice.invoices)
Hope, this helps someone like me - novice in redux :)
P.S. final code is here

How can I display the data of an array from an API?

i'm having a problem displaying the data from the punkbeer API and would appreciate any kind of help
import { useEffect, useState, Fragment } from 'react';
import { Switch, Link, Route, BrowserRouter as Router } from 'react-router-dom';
import React from 'react'
import '../Drink/drinks.css';
function Drinks() {
const [beer, setBeer] = useState('[]');
const [selectedBeer, setSelectedBeer] = useState("")
const fetchDrinks = function() {
fetch(`https://api.punkapi.com/v2/beers`)
.then( function(result) {
return result.json()
})
.then(function (data) {
setBeer(data)
data.forEach(beer => {
<div>
<div className="drink-img">
<img src="{beer.image_url}"/>
</div>
<div className="drink-title">
<h2>{beer.name}</h2> </div>
<div className="drink-tagline">
<h2>{beer.tagline}</h2> </div>
<div className="drink-food">
<h2>{beer.food_pairing}</h2> </div>
</div>
});
})
.catch(function () {
});
}
useEffect( function(){
fetchDrinks();
}, []);
return (
<div className="drink-container">
<div className="next">
<p>After you are picked your drink, click next to place your order </p>
<Link to="./Order">
<button className="btn" >Order</button>
</Link>
</div>
</div>
)
}
export default Drinks
You can save the return in variable/state.
Example you save in variabe that have name "data"
in view, you can add this
{data.map((value,index)=>{
return(
<div key={index}>
<div className="drink-img">
<img src="{value.image_url}"/>
</div>
<div className="drink-title">
<h2>{value.name}</h2> </div>
<div className="drink-tagline">
<h2>{value.tagline}</h2> </div>
<div className="drink-food">
<h2>{value.food_pairing}</h2> </div>
</div>
)}
)}

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>
);

Countries End point is not returning anything although works in sandbox

I am building a small Countries App in React. The issue I have is that I have changed the endpoint and now it is not returning anything. I checked this in Sandbox and it worked fine. Below is the code for the page that renders the details of the country.
import React from 'react';
import { useEffect } from "react";
import { useState } from "react";
import { NavBarCard } from '../NavBar/NavBarCard';
import './DetailCountryCard.css';
import {Link} from 'react-router-dom';
function DetailCountryCard ({ match }) {
useEffect(() => {
fetchItem();
console.log(match);
// eslint-disable-next-line
}, []);
const [country, setCountry] = useState({});
const [darkMode, setDarkMode] = useState(false);
const fetchItem = async () => {
const fetchItem = await fetch(
`https://restcountries.eu/rest/v2/alpha/${match.params.alpha3Code}`
);
const country = await fetchItem.json();
setCountry(country);
console.log(country);
};
return (
// <div>
// <h1>the country</h1>
// </div>
<div className={darkMode ? "dark-mode" : "light-mode" }>
<NavBarCard handlechange={()=> setDarkMode(prevMode => !prevMode)} moonMode={darkMode ? "moon fas fa-moon" :
"moon far fa-moon"}
darkMode={darkMode ? "dark-mode" : "light-mode"}/>
<div className="detailCard">
<Link to="/">
<button className="topButton myButton">Back</button>
</Link>
<div className="container">
<img className="flag" alt="flag" src={country.flag} />
<div className="countryName">
<div className="NativeName">
<h1 className="Country">{country.name}</h1>
<h2>Native Name:</h2>
<p> {country.nativeName}</p>
<br />
<h2>Population:</h2>
<p> {country.population}</p>
<br />
<h2>Region:</h2>
<p> {country.region}</p>
<br />
<h2>Sub Region:</h2>
<p> {country.subregion}</p>
<br />
<h2>Capital:</h2>
<p> {country.capital}</p>
<br />
<div>
<h2>Border Countries:</h2>{country.borders && country.borders.map(function(border){
return(
<Link to={`/DetailCard/${border}`}>
<button className="myButton"> {border} </button>
</Link>
)
})}
</div>
</div>
</div>
<div className="domain">
<h2>Top Level Domain: </h2>
<p>{country.topLevelDomain}</p>
<br />
<h2>Currencies: </h2>
<p>{country.currencies && country.currencies.map(({ name }) => name).join(", ")}</p>
<br />
<h2>Languages: </h2>
<p>{country.languages && country.languages.map(({ name }) => name).join(", ")}</p>
<br />
</div>
</div>
</div>
</div>
);
}
export default DetailCountryCard;
All I get is blank page and in the console it saying that I am getting a status of 400. Any help would be appreciated. If I just put bra as the last three letters of the alpha code this is what I get.

Resources