Calling data from the API for child component in Next.js - javascript

I am working on a header component. Here is the code:
import style from '../../styles/header.css';
import '../../styles/globals.css';
export default function Header({data}){
const [showMe, setShowMe] = useState(false);
function toggle(){
console.log("toggle")
setShowMe(!showMe);
}
return(
<>
<div className="header">
<div className="web-header">
<div className="first-header">
<div className="info-strip">
<ul>
<li>
Contact Us
</li>
<li>
7 Day Returns
</li>
<li>
Track Order
</li>
<li>
Return Order
</li>
<li>
Survey
</li>
</ul>
</div>
<div className="right-block d-flex">
<div className="login">
<span className="image"></span>
<span className="text">Log In
<div className="account-box">
</div>
</span>
</div>
<div className="cart">
<span className="cart-image">
</span>
<span className="text">Cart</span>
</div>
</div>
</div>
<div className="second-header">
<div className="header-logo">
<img src="https://www.mirraw.com/assets/logo-red.png" />
</div>
<div className="search">
<input placeholder="Search Something.." />
<button></button>
</div>
</div>
<div className="third-header">
<div className="container-fluid">
<ul className="menu">
{data.menus.map((post, index) => {
return (
<li className="menu-list">
{post.title}
<div className="megabox">
<ul className="wrapper">
{post.menu_columns.map((subItems, sIndex) => {
return <li>
<span className="menu-link">
{subItems.title}
</span>
<ul className="category">
{subItems.menu_items.map((x) => {
return <li>
{x.title}
</li>
})}
</ul>
</li>;
})}
</ul>
</div>
</li>)})}
</ul>
</div>
</div>
</div>
<div className="mobile-screen">
<div className="mobile-header">
<div className="mobile-menu">
<div className="menu-icon">
<div className="wrapper">
<input type="checkbox" id="navigation" />
<label for="navigation">
+
</label>
<div className="right-card">
<img src="https://www.mirraw.com/assets/logo-red.png" />
<p className="app-install">
<span>Download app</span>
</p>
<div className="cart">
<span className="cart-image"></span>
{/* <span className="text">Cart</span> */}
</div>
</div>
<nav>
<ul>
<li className="menu-heading">
<span>Menu</span>
<span>
<label for="navigation">X</label>
</span>
</li>
{data.menus.map((post, index) => {
return (
<li className="menu-list">
{post.title} <span onClick={toggle}>+</span>
<ul style={{display: showMe?"block":"none"}} className="category-one">
{post.menu_columns.map((subItems, sIndex) => {
return <li>
{subItems.title}
<span>+</span>
<ul className="category-two">
{subItems.menu_items.map((x) => {
return <li>
{x.title}
</li>
})}
</ul>
</li>;
})}
</ul>
</li>)})}
</ul>
</nav>
</div>
</div>
</div>
<div className="scroll-menu-list">
<ul className="mb-0">
{data.menus.map((post, index) => {
return (
<li className="menu-list">{post.title}</li>
)})}
</ul>
</div>
</div>
</div>
</div>
</>
)
}
export async function getServerSideProps() {
// Fetch data from external API
const res = await fetch(`https://api.mirraw.com/api/v1/menu`);
const data = await res.json();
// Pass data to the page via props
return { props: { data } }
}
Code is working fine if I render this page only, but when I import this component in other component, it threw error:
Server Error
TypeError: Cannot read property 'menus' of undefined
This error happened while generating the page. Any console logs will be displayed in the terminal window.
What could be the approach of getting value from the API for child component?

getServerSideProps can only be used within page components, which is why it works when you render this component as a page.
If you want to this to be a reusable component that can be called from other components and/or pages you'll need to pass the data you get at the page level (from getServerSideProps, for instance) down to it.
// pages/index.js
import Header from "../components/header"
export default function IndexPage({ data }) {
return (
<Header data={data} />
)
}
export async function getServerSideProps() {
const res = await fetch(`https://api.mirraw.com/api/v1/menu`);
const data = await res.json();
return { props: { data } }
}

Related

document.querySelector is not working in my react component

function Slider() {
const track=document.querySelector('.slide__track')//To access the div with class slide track
console.log(track);
return (
<div className="slider">
<i className="fas fa-chevron-left"></i>
<div className="head">
<h1 className="title">Based on your last search</h1>
<h6>View more</h6>
</div>
<div className="slider_container">
<ul className="slider__track">
<li className="slider__items">
<Card />
</li>
</ul>
</div>
<i className="fas fa-chevron-right"></i>
</div>
);
}
i cannot access the div with class slide__track.
What is the problem here?
Or how can i access that element?
Try and use this code in useEffect()
useEffect(() => {
const track = document.querySelector('.slide__track')
// have access to it
}, []);
I think it's because it is running before the DOM has been rendered. Move the track code into useEffect.
import {useEffect} from "react";
function Slider() {
useEffect(() => {
const track=document.querySelector('.slide__track')//To access the div with class slide track
console.log(track);
});
return (
<div className="slider">
<i className="fas fa-chevron-left"></i>
<div className="head">
<h1 className="title">Based on your last search</h1>
<h6>View more</h6>
</div>
<div className="slider_container">
<ul className="slider__track">
<li className="slider__items">
<Card />
</li>
</ul>
</div>
<i className="fas fa-chevron-right"></i>
</div>
);
}
You should be probably be using ref's to access dom elements inside react. see docs: https://reactjs.org/docs/refs-and-the-dom.html - reason being, if you have the below in a loop, or have multiple instances on the page, you'll need to be more careful with the selector approach.
import React, { useRef, useEffect } from 'react';
function Slider() {
const slideTrackRef = useRef(null);
useEffect(() => {
if (slideTrackRef && slideTrackRef.current) {
console.log(slideTrackRef.current);
}
}, [slideTrackRef]);
return (
<div className="slider">
<i className="fas fa-chevron-left" />
<div className="head">
<h1 className="title">Based on your last search</h1>
<h6>View more</h6>
</div>
<div className="slider_container">
<ul className="slider__track" ref={slideTrackRef}>
<li className="slider__items">
<p>tst</p>
</li>
</ul>
</div>
<i className="fas fa-chevron-right" />
</div>
);
}
export default Slider;

toggle background color on a function - ReactJS

When I clicked a link it renders a view based on the "id" from a JSON. I need to apply a background color when a certain view renders. And I should toggle the Style.
This code shows the crawl when I clicked a particular link.
handleCrawl = e => {
const { id } = e.target;
this.setState(current => ({
showCrawl: { [id]: !current.showCrawl[id] }
}));
};
This is my render method where Ia am mapping the links and the additional details on JSON
render() {
return (
<div class="d-flex" id="wrapper">
<div class="bg-light border-right" id="sidebar-wrapper">
<h1 class="sidebar-heading">API</h1>
<ul class="list-group list-group-flush">
{this.state.apis.map(api => (
<li><a class="list-group-item list-group-item-action bg-light" key={api.id}
id={api.id}
onClick={this.handleCrawl}>{api.title}</a></li>
))}
</ul>
</div>
<div id="page-content-wrapper">
<div class="container-fluid">
{this.state.apis.map(api => (
<div
key={api.id}
id={api.id}>
{this.state.showCrawl[api.id] && (
<SwaggerUI url={api.opening_crawl}/>
)}
</div>
))}
</div>
</div>
</div>
);
}
Not sure if it answers your question.
You can toggle the style conditionally.
{this.state.apis.map(api => (
<div
key={api.id}
id={api.id}
className={this.state.showCrawl[api.id]?"some-specific-style":"default-or-empty"}
>
{this.state.showCrawl[api.id] && (
<SwaggerUI url={api.opening_crawl}/>
)}
</div>
))}

Maximum depth exceeded when trying to redirect from child state to parent state

I am trying to pass data from child to parent state using
I have to state ProjectList and Header, the header(website header) state is the child compenent of parent, there links on header,if it clicks the link then I am getting an id through that link and then passing that id to through redirect.
but it gives me error maximum dept exceeded.The id I want to passs from header to project list is also coming from other state which is not the child of project list.
ProjectList State:
class ProjectList extends React.Component{
constructor(props){
super(props);
this.showDetail=this.showDetail.bind(this);
this.state={
category_projects:[],
projectPage:false,
clk_project:null,
category:[]
}
}
componentDidMount() {
fetch(`http://127.0.0.1:8000/portfolio/get_category_project/`+this.props.match.params.id+'/').then(response => response.json())
.then(projectsJson => this.setState({category_projects: projectsJson},()=>{
this.sortProjects()
}))
fetch('http://127.0.0.1:8000/portfolio/create_category/')
.then(response=>response.json())
.then(categoryJson => this.setState({category: categoryJson},()=>{
this.sortCategory()
}))
}
sortCategory = ()=>{
let sortArray=this.state.category;
let swap;
for (let i=0;i<sortArray.length;i++)
{
for (let j=0;j<sortArray.length;j++){
if(sortArray[i].category_rank>sortArray[j].category_rank){
swap=sortArray[i];
sortArray[i]= sortArray[j];
sortArray[j]=swap;
}
}
}
this.setState({category:sortArray})
};
showDetail=(evt)=>{
evt.preventDefault();
this.setState({projectPage:true});
this.setState({clk_project:JSON.parse(evt.currentTarget.getAttribute('data-item'))});
};
sortProjects=()=>{
let sortArray=this.state.category_projects;
let swap;
for (let i=0;i<sortArray.length;i++)
{
for (let j=0;j<sortArray.length;j++){
if(sortArray[i].project_rank>sortArray[j].project_rank){
swap=sortArray[i];
sortArray[i]= sortArray[j];
sortArray[j]=swap;
}
}
}
this.setState({category_projects:sortArray})
};
render() {
let redirect=null;
if (this.state.projectPage){
redirect=<Redirect to={`/project/${this.state.clk_project.id}`}/>
}
return(
<div>
{redirect}
<div className="site_wrapper">
<div className="clearfix">
</div>
<Header category={this.state.category}/>
<div className="clearfix">
</div>
<div className="page_title2">
<div className="container">
<div className="title"><h2>Projects</h2></div>
</div>
</div>
<div className="clearfix">
</div>
<div className="container">
<br />
{this.state.category_projects.map(proj=>{
return(
<div className="column">
<img data-item={JSON.stringify(proj)} onClick={this.showDetail} src={"http://127.0.0.1:8000"+proj.file} alt="Snow" className="ImgWidth"/>
</div>
)
})}
</div>
<div className="clearfix margin_top5">
</div>
<div className="footer_graph">
</div>
<Footer projects={this.state.category_projects} id={this.props.match.params.id}/>
</div>
</div>
)
}
}
Header State:
class Header extends React.Component{
constructor(props){
super(props);
this.showCatDetail=this.showCatDetail.bind(this);
this.state={
category:[],
clk_category:[],
detail:false
}
}
showCatDetail=(e)=>{
e.preventDefault();
this.setState({detail:true,clk_category:JSON.parse(e.currentTarget.getAttribute('data-item'))},()=>{
console.log(this.state.clk_category)
});
};
render(){
let hreflink=null;
let redirect=null;
if (this.state.detail){
redirect=<Redirect to={`/category_project/${this.state.clk_category.id}`}/>
}
return(
<div>
{redirect}
<header id="header">
<div id="trueHeader">
<div className="wrapper">
<div className="container">
<div className="logo">
<a href={hreflink} id="logo">
</a>
</div>
<div className="menu_main">
<div className="navbar yamm navbar-default">
<div className="container">
<div className="navbar-header">
<div className="visibledevice">
<ul className="nav navbar-nav">
<li><a href={hreflink} className="active">
<i className="fa fa-home">
</i> Home</a></li>
</ul>
</div>
</div>
<div className="navbar-collapse collapse pull-right">
<ul className="nav navbar-nav">
<li><a href={hreflink} className="active">
<i className="fa fa-home">
</i> Contact Us</a></li>
{this.props.category.map(cat=>{
return(
<li data-item={JSON.stringify(cat)} onClick={(e)=>this.showCatDetail(e)}><a href={hreflink} >
<i className="fa fa-home">
</i>{cat.category_name}</a></li>
)
})}
</ul>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</header>
</div>
)
}
}
this.props.match.params.id this id I want to get from header as I trying to pass from in header.The this.props.match.params.id in project list can come from Header or other state.Please need suggestion how to pass this id from header to project list as well as the id can comes from other state to project.

Converting JavaScript to work with React component

New to React and am trying to write my script in React but not sure how to do it.I've tried using states but that has just clouded me with more confusion. The below code is a sample of something I might commonly create.
Here's my script:
const hamburger = document.querySelector(".hamburger");
hamburger.addEventListener("click", function () {
hamburger.classList.toggle("is-active");
document.querySelector(".navigation").classList.toggle("slide-in");
document.querySelector("body").classList.toggle("menu-active");
document.querySelector(".shell-ui-main").classList.toggle("menu-overlay");
});
Here's a basic react component for a navbar:
import React from 'react';
export default class NavComponent extends React.Component {
render() {
return (
<div className="container">
<button className="hamburger hamburger--squeeze" type="button">
<span className="hamburger-box">
<span className="hamburger-inner"></span>
</span>
</button>
<a className="logo-link" href="/">
<img width="94" height="31" src="/img/logos/logo.png" srcSet="/img/logos/logo.png 1x, /img/logos/logo#2x.png 2x, /img/logos/logo#3x.png 3x"
alt="logo" className="logo" />
</a>
<nav className="navigation">
<ul className="nav">
<li className="single-item">
Home
</li>
<li className="single-item">
Item 2
</li>
<li className="single-item">
Item 3
</li>
<li className="single-item">
Item 4
</li>
</ul>
</nav>
</div>
);
}
}
Here's the solution in case anyone is interested. Additionally I pass the props down to the component and control from there instead of the individual const.
import React from 'react';
const HamburgerToggle = (props) => (
<button className={"hamburger hamburger--squeeze" + (props.active ? " is-active" : "")} onClick={props.clickHandler} type="button">
<span className="hamburger-box">
<span className="hamburger-inner"></span>
</span>
</button>
);
const Logo = () => (
<a className="logo-link" href="/">
<img width="94" height="31" src="/img/logos/logo.png" srcSet="/img/logos/logo.png 1x, /img/logos/logo#2x.png 2x, /img/logos/logo#3x.png 3x" alt="Logo" className="logo" />
</a>
);
const Navigation = (props) => (
<nav className={"navigation" + (props.active ? " slide-in" : "")}>
<ul className="nav">
<li className="single-item">
Home
</li>
<li className="single-item">
intem 2
</li>
<li className="single-item">
item 3
</li>
<li className="single-item">
item 4
</li>
</ul>
</nav>
);
export default class NavComponent extends React.Component {
state = {active: false};
handleClick(e){
this.setState({active: !this.state.active});
console.log(this.state.active);
}
render() {
return (
<div className="container">
<HamburgerToggle active={this.state.active} clickHandler={this.handleClick.bind(this)} />
<Logo />
<Navigation active={this.state.active} clickHandler={this.handleClick.bind(this)} />
</div>
);
}
}

ReactJs Cannot read property 'props' of undefined

I have react js code of inner most child component like this
import React from 'react'
import { addToCart } from 'actions/cart'
export default (props) => {
const { line_item, cart} = props
// const oClick = line_item.oClick.bind(line_item)
const handleClick = (id) => this.props.dispatch(addToCart(id, 1))
// *I am getting error above line*
return (
<div>
<ul className="ul-reset">
<li>
<div className="cart-prod-wrapper cf">
<div className="cart-image-wrapper">
<div className="cart-image">
<a href="#"><img src="#" alt="Product One"/>
</a>
</div>
</div>
<div className="cart-details">
<div className="cart-name">
{line_item.variant.name}
</div>
<div className="cart-price">{line_item.variant.price}</div>
</div>
<div className="cart-qty">
<div className="cart-qty-name">QTY:</div>
<div className="cart-qty-value">
<div class="minus"><span>-</span></div>
{line_item.quantity}
<div class="plus">
<span value = { line_item.variant.id } onClick={handleClick(line_item.variant.id)} >+</span></div>
</div>
</div>
<div className="cart-total">
<div className="cart-total-name">Total</div>
<div className="cart-total-value">{line_item.variant.price * line_item.quantity}</div>
</div>
</div>
</li>
</ul>
</div>
)
}
i want to perform to call an action using dispatch
and code of parent presentation component is line
export default (props) => {
const { account, cart, readMore1} = props
return (
<li>
{ !cart.isFetching && cart.line_items.map(
(line_item, i) => <CartPreview key = {i} line_item= {line_item} cart ={cart} />)
}
</li>
)
}
can any on please guide me to solve this error
Edit
const mapStateToProps = (state) => {
return {
account: getAccount(state),
cart: getCart(state),
classToSend: getReadmore(state),
authenticityToken: getAuthenticityToken(state)
}
}
export default connect(mapStateToProps)(HeaderContainer)
May be this could help
import React from 'react'
import { connect } from 'react-redux' // import connect from redux
import { addToCart } from 'actions/cart'
// name component to wrap it with connect
const MyComponent = (props) => {
const { line_item, cart} = props
return (
<div>
<ul className="ul-reset">
<li>
<div className="cart-prod-wrapper cf">
<div className="cart-image-wrapper">
<div className="cart-image">
<a href="#"><img src="#" alt="Product One"/>
</a>
</div>
</div>
<div className="cart-details">
<div className="cart-name">
{line_item.variant.name}
</div>
<div className="cart-price">{line_item.variant.price}</div>
</div>
<div className="cart-qty">
<div className="cart-qty-name">QTY:</div>
<div className="cart-qty-value">
<div class="minus"><span>-</span></div>
{line_item.quantity}
<div class="plus">
// used arrow function
<span value = { line_item.variant.id } onClick={() => props.dispatch(addToCart(line_item.variant.id, 1)} >+</span></div>
</div>
</div>
<div className="cart-total">
<div className="cart-total-name">Total</div>
<div className="cart-total-value">{line_item.variant.price * line_item.quantity}</div>
</div>
</div>
</li>
</ul>
</div>
)
}
export default connect()(MyComponent); // connect dispatch to component

Categories

Resources