How to anchor a component with prop? - reactjs

I have a website that I used fixed menu options to anchor to the place I wanted ,below is a simple structure to demonstrate
mypage.jsx
<div className="mywork">
<TopbarWork menuOpen={menuOpen} setMenuOpen={setMenuOpen}/>
<MenuWork menuOpen={menuOpen} setMenuOpen={setMenuOpen}/>
<div className="sections">
<Product /> //origin
<Story workData={workData}/> //what I want to achieve
<Userflow workData = {workData}/>
<System workData={workData}/>
<FinalDesign workData={workData}/>
</div>
</div>
menu.jsx(click to go to the different anchors)
import './menu.scss'
export default function Menu({menuOpen,setMenuOpen}) {
return (
<div className={"menu " + (menuOpen && "active")}>
<ul>
<li onClick={()=>setMenuOpen(false)}>
Back
</li>
<li onClick={()=>setMenuOpen(false)}>
product
</li>
</ul>
</div>
)
}
Product.jsx(one of the components)
import { CheckCircle } from '#material-ui/icons';
import './product.scss'
export default function Product({workData}) {
return (
<div className="product" id="product"> //important
<div className="productLeft">
<div className="productIntro">
<p className="title">
{workData.title}
</p>
<p className="desc">
{workData.desc}
</p>
{workData.featured.map((feature)=>{
return(
<div className="featured">
<CheckCircle className="featuredIcon"/>
{feature.title}
</div>
)
})}
</div>
</div>
<div className="productRight">
<div className="item">
<img src="assets/desktop.jpeg" alt="" className="desktopImg" />
<img src={workData.productImg} alt="" className="productImg" />
</div>
</div>
</div>
)
}
So right now the problem is I have to pass "workData" into components , but after that if I click on the anchor, it would show Cannot read properties of undefined (reading 'workData') , I assume that I have to pass the workData too when I click on the anchor ?
But what's the right way to do that ?
EDIT
I tried using Link and history (react-router-dom) but failed , here's my code
menu.jsx
export default function MenuWork({menuOpen,setMenuOpen,workData}) {
console.log(workData)
const history = useHistory();
const handleClick = ()=>{
setMenuOpen(false)
history.push({
pathname:'/mywork#userflow',
state: { workData:workData}
})
}
return (
<div className={"menu " + (menuOpen && "active")}>
<ul>
<li onClick={()=>setMenuOpen(false)}>
Back
</li>
<li onClick={()=>setMenuOpen(false)}>
<Link to="#product">Product</Link>
</li>
<li onClick={()=>setMenuOpen(false)}>
<Link to={{
pathname:"/mywork#story",
state:{ workData:workData}
}}>Story</Link>
</li>
<li onClick={()=>handleClick()}>
userflow
</li>
</ul>
</div>
)
}
If I use Link and pass the state, it will return blank page without loading anything, and If I don't pass any state with Link , it will shows the same error as above.

Related

why link doesn't work when I use getStaticProps?

I'm new in next js and I'm working on project using NextJS. I have some lots in my items page that shows lots currently(pagination/items.tsx) and I also have lotDetails page that I want it to show details of each lot using dynamic route(lotDetails\id\index.tsx).
This is the folder structure:
Now when I click the Link in Items.tsx I expect it to go to lotDetails page and pass the props, but nothing happens! (It stays on Items page!). here is Items.tsx:
import React from 'react'
import Link from "next/link"
const Items = ({currentItems}:{currentItems:any}) => {
console.log(currentItems)
// const ids=currentItems.map((el:any)=>el.id)
// const paths=ids.map((el:any)=>{params:{id:el.toString()}})
// console.log(paths)
return (
<>
<div className="container">
<div className="row">
{currentItems.map((el:any)=><div className="col-md-3 ">
//this should be linked to lotDetails page!
<Link href={{pathname:"../lotDetails/[id]",query:{id:JSON.stringify(el.id),title:el.title,image:el.image,description:el.description.toString(),rate:el.rating.rate,count:el.rating.count,price:el.price},}} as={`/lotDetails/${el.id.toString()}`}>
<div className="lot">
<div className="img-container">
<img src={el.image}/>
</div>
<div className="title">
{el.title}
</div>
<div className="price">
<span className="price-title">Price:</span>
<span>{el.price}</span>
</div>
</div>
</Link>
</div>)}
</div>
</div>
</>
)
}
export default Items;
I'm using getStaticProps and GetStaticPaths in lotDetails:
const LotDetails = (props:any) => {
const dispatch=useDispatch();
console.log(props)
const lotCount=1;
const addLots=()=>{
dispatch(AddCustomerLot({...props,lotCount:lotCount}))
}
return (
<>
<div className='container lot-details'>
<div className="row" >
<div className="col-md-6">
<div className="detail-container">
<div className="title-details"><h3>{props.title}</h3></div>
<div className="badge"><FontAwesomeIcon icon={faStar}/><span>{props.rate}</span></div>
<div className="inventory">
Inventory: <span className="count">{props.count}</span>
</div>
<div className="description-details">{props.description}</div>
<div className="price">Price: <span className="price-number">{props.price}$</span> </div>
<button className="btn btn-regist" onClick={addLots}>Add to shopping basket</button>
</div>
</div>
<div className="col-md-6"><img src={props.image} alt="" /></div>
</div>
</div>
</>
)
}
export const getStaticPaths:GetStaticPaths=async(context:any)=>{
const response= await axios.get("https://fakestoreapi.com/products")
const paths=response.data.map((el:any)=>({params:{id:el.id.toString()}}))
console.log(paths)
return{
paths,
fallback:'blocking'
}
}
export const getStaticProps:GetStaticProps=async(context:any)=>{
return{
props:
{
//recieve props
id:context.query.id,
title:context.query.title,
image:context.query.image,
description:context.query.description,
rate:context.query.rate,
count:context.query.count,
price:context.query.price
}
}
}
export default LotDetails;
when I deleted getStaticProps and getStaticPaths, the link worked! So I receive that link works perfectly and the problem is in getStaticProps and getStaticPaths. Of course I don't want to use getServerSideProps.
Update
According to julio's suggestion I changed pathName, and I also changed context.query to context.params.id:
Items:
<Link href={{pathname:`/lotDetails/${el.id}`,query:{id:JSON.stringify(el.id),title:el.title,image:el.image,description:el.description.toString(),rate:el.rating.rate,count:el.rating.count,price:el.price},}} as={`/lotDetails/${el.id.toString()}`}>
<div className="lot">
<div className="img-container">
<img src={el.image}/>
</div>
<div className="title">
{el.title}
</div>
<div className="price">
<span className="price-title">Price:</span>
<span>{el.price}</span>
</div>
</div>
</Link>
lotDetails:
return (
<>
<div className='container lot-details'>
<div className="row" >
<div className="col-md-6">
//I removed all section which used props and querys using comments
{/* <div className="detail-container">
<div className="title-details"><h3>{props.title}</h3></div>
<div className="badge"><FontAwesomeIcon icon={faStar}/><span>{props.rate}</span></div>
<div className="inventory">
Inventory: <span className="count">{props.count}</span>
</div>
<div className="description-details">{props.description}</div>
<div className="price">Price: <span className="price-number">{props.price}$</span> </div>
<button className="btn btn-regist" onClick={addLots}>Add to shopping basket</button>
</div> */}
</div>
{/* <div className="col-md-6"><img src={props.image} alt="" /></div> */}
</div>
</div>
</>
)
}
export const getStaticPaths:GetStaticPaths=async(context:any)=>{
const response= await axios.get("https://fakestoreapi.com/products")
const paths=response.data.map((el:any)=>({params:{id:el.id.toString()}}))
console.log(paths)
return{
paths,
fallback:'blocking'
}
}
export const getStaticProps:GetStaticProps=async(context:any)=>{
return{
props:
{
id:context.params.id,
// title:context.query.title,
// image:context.query.image,
// description:context.query.description,
// rate:context.query.rate,
// count:context.query.count,
// price:context.query.price
}
}
}
Finally, I solved problem in two steps:
1-I'm using google chrome browser, so I configured chrome and added my localhost port:
I used this link: chrome://inspect/, clicked configure button and added my localhost port(in my case localhost:3000)
2-I added this code to lotDetails page(the page which I used axios)
axios.defaults.httpsAgent=new https.Agent({
rejectUnauthorized:false,
})
don't forget to import:
import https from "https"
Now It's working.

How do I create a portal for this navbar (React)

This is my index.html (Where the portal is supposed to lead to)
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="navbarRoot"></div>
<div id="root"></div>
</body>
Here is my navbar component
const Navbar = () => {
const [isOpen , setIsOpen] = useState(false)
const navButtonHandler = () => {
setIsOpen(!isOpen)
}
return (
<>
<nav className='navbar'>
<span><img src={logo} alt='home' className='logo' /></span>
<div className={`menuMask ${isOpen && "open"}`} onClick={navButtonHandler}></div>
<div className={`menuContainer ${isOpen && "open"}`}>
<ul className={`navitems ${isOpen && "open"}`}>
<a href="/" className='home'>
<li>Home</li>
</a>
<a href="/" className='whoWeHelp'>
<li>Who We Help</li>
</a>
<a href="/" className='services'>
<li>Services</li>
</a>
<a href="/" className='about'>
<li>About</li>
</a>
<a href="/" className='caseStudies'>
<li>Case Studies</li>
</a>
<li>
<PrimaryButton link={'https://hadizouhbi.website'}>Client Login</PrimaryButton>
</li>
<li>
<SecondaryButton link={'https://hadizouhbi.website'}>Contact</SecondaryButton>
</li>
</ul>
</div>
<div className={`navToggle ${isOpen && "open"}`} onClick={navButtonHandler}>
<div className='bar'>
</div>
</div>
</nav>
</>
)
}
Where in the code do I use this
{ReactDom.createPortal(<Navbar />, document.getElementById('navbarRoot'))}
Am i doing something wrong? because I have no idea where to put that line however I do think the syntax for that is correct just where to put it is the issue. Any help is greatly appreciated ! I am a beginner to react
If you meant to render the whole NavBar component as a portal then return in the Navbar should be like below.
import { useState } from "react";
import ReactDOM from "react-dom";
const domNode = document.getElementById("navbarRoot");
const Navbar = () => {
const [isOpen, setIsOpen] = useState(false);
const navButtonHandler = () => {
setIsOpen(!isOpen);
};
const navContent = (
<>
<nav className="navbar">
<span>{/* <img src={logo} alt="home" className="logo" /> */}</span>
<div
className={`menuMask ${isOpen && "open"}`}
onClick={navButtonHandler}
></div>
<div className={`menuContainer ${isOpen && "open"}`}>
<ul className={`navitems ${isOpen && "open"}`}>
<a href="/" className="home">
<li>Home</li>
</a>
...
...
</ul>
</div>
<div
className={`navToggle ${isOpen && "open"}`}
onClick={navButtonHandler}
>
<div className="bar"></div>
</div>
</nav>
</>
);
return ReactDOM.createPortal(navContent, domNode);
};
Use Navbar in any other place. In spite of where you try to render it in your component tree, it will always appear in the div with navbarRoot as the id.
export default function App() {
return (
<div className="App">
<Navbar />
</div>
);
}
the code {ReactDom.createPortal(<Navbar />, document.getElementById('navbarRoot'))} goes inside the return statement.
eg:
import Navbar from "component"
function MainPage(){
...
...
return(
<>
...
{ReactDom.createPortal(<Navbar />, document.getElementById('navbarRoot'))}
</>
);
}

How can I use ref for another component?

So I have a sidebar with list of items, and when I click on an item, it should scroll to a certain div, which are outside components. Sidebar looks like this:
Sidebar component:
const Sidebar = () => {
const [sideBar, setSidebar] = useState(false);
return (
<div className="sidebar">
<span class="btn" onClick={() => setSidebar(!sideBar)}>Menu</span>
<div className="profile">
<img src={spike}/>
<span>Alim Budaev</span>
<span>Available for work</span>
</div>
<ul className="sidebarlist" id={sideBar ? "hidden" : ""}>
{SlidebarData.map((val,key) =>{
return (
<li
className="row"
id={window.location.pathname === val.link ? "active" : ""}
key={key}
onClick={()=> {
}}>
{""}
<div>
{val.title}
</div>
</li>
);
})}
</ul>
</div>
);
}
Components in App.js:
function App() {
return (
<div className="App">
<div className="header">
<Sidebar/>
<Hero">
<Particles/>
</Hero>
<About/>
<Service/>
<Form/>
<Footer/>
</div>
</div>
);
}
So I'm looking to way to scroll to a certain component when I click on . I know it can be made through useRef(), but I don't know how to do it in the Sidebar with outside components.

How Can I set State in stateless Function, in a nested Function?

I know that I can't change the state in a stateless function when the function is nested, though I am only this far away to set the state in order for the page work as I would want. I want to keep this as a functional component. The issue is below I want to set the language under this function, or any other way works I know how to do this with Class component, though unless there will be 10 votes to do that would prefer to stay with functional.
function changeTounge(e) {
console.log("Write something!!");
console.log(e.currentTarget.dataset.id);
console.log(e.currentTarget.dataset.value);
//setLanguage({ iso2: "lv", speak: "Latviešu" });
}
the full code is:
import React, { useState } from "react";
import { Link } from "react-router-dom";
export function PrimaryNav() {
const [language, setLanguage] = useState({ iso2: "us", speak: "English" });
return (
<div className="primary-nav">
<ul className="navigation">
<li className="active">
<Link to="/">Home</Link>
</li>
<li className="has-child">
Opportunities
<div className="wrapper">
<div id="nav-homepages" className="nav-wrapper">
<ul>
{OpsOption("RealEstate", "Real Estate")}
{OpsOption("Vehicles", "Vehicles")}
{OpsOption("JobSearch", "Job Search")}
{OpsOption("PersonalCompany", "Personal Company")}
{OpsOption("Inves`enter code here`tInIdea", "Invest In Idea")}
</ul>
</div>
</div>
</li>
<li>
<Link to="/contact">Help & Support</Link>
</li>
<li className="has-child language">
{ActiveLanguage(language.iso2, language.speak)}
<div className="wrapper">
<div id="nav-languages" className="nav-wrapper">
<ul>
{LanguageOption("English", "us")}
{LanguageOption("British", "gb")}
{LanguageOption("Latviešu", "lv")}
{LanguageOption("Estonia", "ee")}
{LanguageOption("Lithuania", "lt")}
{LanguageOption("Russian", "ru")}
{LanguageOption("Deutch", "de")}
{LanguageOption("French", "fr")}
</ul>
</div>
</div>
</li>
</ul>
</div>
);
}
function LanguageOption(label, classLabel) {
return (
<li
onClick={changeTounge.bind(this)}
data-id={label}
data-value={classLabel}
>
<Link to="#nav-locations">
<span className={"flag-icon flag-icon-" + classLabel}></span>
{" "}
{label}
</Link>
</li>
);
}
function changeTounge(e) {
console.log("Write something!!");
console.log(e.currentTarget.dataset.id);
console.log(e.currentTarget.dataset.value);
//setLanguage({ iso2: "lv", speak: "Latviešu" });
}
function OpsOption(pageLink, label) {
return (
<li>
<Link to={"/" + pageLink}>{label}</Link>
</li>
);
}
function ActiveLanguage(iso2, activeLanguage) {
return (
<a href="#nav-languages">
<span className={"flag-icon flag-icon-" + iso2}></span> {activeLanguage}
</a>
);
}
export default PrimaryNav;
Try nesting the components inside of the main component, they'll be able to access and set its state. This is still a functional pattern here.
The other option would be to add a prop to your children components, and pass in the setLanguage function through that prop.
Also, you don't need the changeTounge.bind.this in functional react :D. In general, if you're using this at all in functional react... that's a red flag.
import React, { useState } from "react";
import { Link } from "react-router-dom";
const PrimaryNav = () => {
const [language, setLanguage] = useState({ iso2: "us", speak: "English" });
const changeTounge = (e) => {
console.log("Write something!!");
console.log(e.currentTarget.dataset.id);
console.log(e.currentTarget.dataset.value);
setLanguage({ iso2: "lv", speak: "Latviešu" });
}
const OpsOption = (pageLink, label) => {
return (
<li>
<Link to={"/" + pageLink}>{label}</Link>
</li>
);
}
const ActiveLanguage = (iso2, activeLanguage) => {
return (
<a href="#nav-languages">
<span className={"flag-icon flag-icon-" + iso2}></span> {activeLanguage}
</a>
);
}
const LanguageOption = (label, classLabel) => {
return (
<li
onClick={changeTounge}
data-id={label}
data-value={classLabel}
>
<Link to="#nav-locations">
<span className={"flag-icon flag-icon-" + classLabel}></span>
{" "}
{label}
</Link>
</li>
);
}
return (
<div className="primary-nav">
<ul className="navigation">
<li className="active">
<Link to="/">Home</Link>
</li>
<li className="has-child">
Opportunities
<div className="wrapper">
<div id="nav-homepages" className="nav-wrapper">
<ul>
{OpsOption("RealEstate", "Real Estate")}
{OpsOption("Vehicles", "Vehicles")}
{OpsOption("JobSearch", "Job Search")}
{OpsOption("PersonalCompany", "Personal Company")}
{OpsOption("Inves`enter code here`tInIdea", "Invest In Idea")}
</ul>
</div>
</div>
</li>
<li>
<Link to="/contact">Help & Support</Link>
</li>
<li className="has-child language">
{ActiveLanguage(language.iso2, language.speak)}
<div className="wrapper">
<div id="nav-languages" className="nav-wrapper">
<ul>
{LanguageOption("English", "us")}
{LanguageOption("British", "gb")}
{LanguageOption("Latviešu", "lv")}
{LanguageOption("Estonia", "ee")}
{LanguageOption("Lithuania", "lt")}
{LanguageOption("Russian", "ru")}
{LanguageOption("Deutch", "de")}
{LanguageOption("French", "fr")}
</ul>
</div>
</div>
</li>
</ul>
</div>
);
}
export default PrimaryNav;
There are probably tidier ways to do some of this, but this seems to work:
import React, { useState } from "react";
import { Link } from "react-router-dom";
export function PrimaryNav() {
const [language, setLanguage] = useState({ iso2: "us", speak: "English" });
return (
<div className="primary-nav">
<ul className="navigation">
<li className="active">
<Link to="/">Home</Link>
</li>
<li className="has-child">
Opportunities
<div className="wrapper">
<div id="nav-homepages" className="nav-wrapper">
<ul>
{OpsOption("RealEstate", "Real Estate")}
{OpsOption("Vehicles", "Vehicles")}
{OpsOption("JobSearch", "Job Search")}
{OpsOption("PersonalCompany", "Personal Company")}
{OpsOption("Inves`enter code here`tInIdea", "Invest In Idea")}
</ul>
</div>
</div>
</li>
<li>
<Link to="/contact">Help & Support</Link>
</li>
<li className="has-child language">
{ActiveLanguage(language.iso2, language.speak)}
<div className="wrapper">
<div id="nav-languages" className="nav-wrapper">
<ul>
{LanguageOption("English", "us", setLanguage)}
{LanguageOption("British", "gb", setLanguage)}
{LanguageOption("Latviešu", "lv", setLanguage)}
{LanguageOption("Estonia", "ee", setLanguage)}
{LanguageOption("Lithuania", "lt", setLanguage)}
{LanguageOption("Russian", "ru", setLanguage)}
{LanguageOption("Deutch", "de", setLanguage)}
{LanguageOption("French", "fr", setLanguage)}
</ul>
</div>
</div>
</li>
</ul>
</div>
);
}
function LanguageOption(label, classLabel, setLanguage) {
return (
<li
onClick={(event) => changeTounge(event, setLanguage, label, classLabel)}
data-id={label}
data-value={classLabel}
>
<Link to="#nav-locations">
<span className={"flag-icon flag-icon-" + classLabel}></span>
{" "}
{label}
</Link>
</li>
);
}
function changeTounge(e, setLanguage, label, classLabel) {
console.log("Write something!!");
console.log(e.currentTarget.dataset.id);
console.log(e.currentTarget.dataset.value);
setLanguage({ iso2: classLabel, speak: label });
}
function OpsOption(pageLink, label) {
return (
<li>
<Link to={"/" + pageLink}>{label}</Link>
</li>
);
}
function ActiveLanguage(iso2, activeLanguage) {
return (
<a href="#nav-languages">
<span className={"flag-icon flag-icon-" + iso2}></span> {activeLanguage}
</a>
);
}
export default PrimaryNav;

ReactJS Preload Navigation Elements

I recently moved my static navigation bar from being a general html element to included in my React rendering for my page because I wanted to incorporate the ability to dynamically load notifications in a modal that can get triggered in the navigation. With this change, I have noticed that my navigation bar does not appear immediately when the page is loaded, but when componentDidMount() { this.fetchList(); } finishes loading.
I personally belief that this is because the navigation component is being set in the render() call involved with this API fetch and since this class is being set after the call is made, then the navigation will have to wait until the fetch comes back successfully or as a failure.
If this is true, does that mean that I need to set my navigation at a higher level to ensure it loads when the page loads with styling and non-react elements?
Here is my ReactDOM.render():
import React from 'react';
import ReactDOM from 'react-dom';
import AnnotationFeedContainer from './components/app/activity-feed/activity-feed.js';
ReactDOM.render(<AnnotationFeedContainer />, document.getElementById('annotation-card'));
Here is <AnnotationFeedContainer /> which is rendering my react elements (<Navigation /> is the component I am looking to load before and regardless of fetchList()):
import React from 'react';
import fetch from 'node-fetch';
import path from 'path';
import Navigation from '../navigation';
import AnnotationSearchForm from './annotation-search-form';
import OnboardingInformation from './onboarding/information';
import ActivityFeedNotifications from './notifications/notifications';
import AnnotationFeed from './annotation-card/annotation-card-feed';
import { API_ROOT } from '../config/api-config';
//GET /api/test and set to state
export default class AnnotationFeedContainer extends React.Component{
constructor(props, context) {
super(props, context);
this.state = this.context.data || window.__INITIAL_STATE__ || { annotations: [], isLoading: true, onboardingWelcome: false, notifications: [] };
}
fetchList() {
fetch(`${API_ROOT}` + '/api' + window.location.search, { compress: false })
.then(res => {
return res.json();
})
.then(data => {
console.log(data);
this.setState({ annotations: data.annotation, user: data.user, csrf: data.csrfToken, isLoading: false, onboardingWelcome: data.onboardingWelcome, notifications: data.notifications, feedPreference: data.feedPreference });
})
.catch(err => {
console.log(err);
});
}
componentDidMount() {
this.fetchList();
}
render() {
if(this.state.feedPreference === 1){
return (
<div>
<Navigation notifications={this.state.notifications}/>
<AnnotationSearchForm />
<div className="activity-feed-container">
<div className="container">
<OnboardingInformation onboarding={this.state.onboardingWelcome}/>
<LoadingIndicator loading={this.state.isLoading} />
<div className="row">
<div className="col-md-12">
<AnnotationFeed {...this.state} />
</div>
</div>
</div>
</div>
</div>
)
} else {
return (
<div className="activity-feed-container">
<div className="container">
<OnboardingInformation onboarding={this.state.onboardingWelcome}/>
<LoadingIndicator loading={this.state.isLoading} />
<div className="row">
<div className="col-md-6 col-md-offset-3">
<AnnotationFeed {...this.state} />
</div>
<div className="col-md-1 col-md-offset-1">
<ActivityFeedNotifications notifications={this.state.notifications} />
</div>
</div>
</div>
</div>
)
}
}
};
//Loading Indicator
const LoadingIndicator = props => {
if(props.loading == true){
return (
<div className="spinner">
<div className="bounce1"></div>
<div className="bounce2"></div>
<div className="bounce3"></div>
<p>Loading...</p>
</div>
)
} else {
return null;
}
}
Navigation Component:
import React from 'react';
import NotificationPopover from './activity-feed/notifications/notifications-popover';
//Navigation
export default class Navigation extends React.Component {
render() {
return (
<nav className="navbar">
<div className="container-fluid">
<div className="navbar-header">
<button type="button" className="navbar-toggle" data-toggle="collapse" data-target="#navigationLinks">
<span className="icon-bar mobile-nav-toggle"></span>
<span className="icon-bar mobile-nav-toggle"></span>
<span className="icon-bar mobile-nav-toggle"></span>
</button>
<a className="navbar-brand" href="/app"><img src="/images/synotate_logo.svg" className="nav-logo-svg"></img></a>
</div>
<div className="collapse navbar-collapse" id="navigationLinks">
<ul className="nav navbar-nav">
<li className="nav-item">
<a className="nav-link" href="/app">Activity Feed</a>
</li>
<li className="nav-item">
<a className="nav-link" href="/app/settings">Settings</a>
</li>
</ul>
<ul className="nav navbar-nav navbar-right">
<li className="nav-item">
<NotificationPopover notifications={this.props.notifications}/>
</li>
<li className="nav-item">
<a className="nav-link" href="/app/logout">Log Out</a>
</li>
</ul>
</div>
</div>
</nav>
)
}
}
in your <AnnotationFeedContainer> you have this line if(this.state.feedPreference === 1) in the render() method.
For that condition wont be true unless you have a successful fetch() event coming from fetchList() in componentDidMount(), and if this condition returns true, you will render what ever is inside the braces of it, which includes the <Navigation> component
Else-wise you will render another code, which is loading indicator I guess, and in here, you didnt include your Navigation component, thus it won't show.
That is the logic you are using, you are telling your app to not include the Navigation component unless it fetches ur data, which happens to be logically fine!
if you want to display it other wise, you may wanna be moving it out of the if statement you have
It seems like you fetch call is responsible for setting the feedPreference variable in your state.
Since this variable is used in your if condition, and the <Navigation/> component isnt rendered when the feedPreference isn't set.
A simple solution would be to add <Navigation/> into the else condition (in the <AnnotationFeedContainer/>'s render function) :
} else {
return (
<>
<Navigation notifications={this.state.notifications}/>
<div className="activity-feed-container">
<div className="container">
<OnboardingInformation onboarding={this.state.onboardingWelcome}/>
<LoadingIndicator loading={this.state.isLoading} />
<div className="row">
<div className="col-md-6 col-md-offset-3">
<AnnotationFeed {...this.state} />
</div>
<div className="col-md-1 col-md-offset-1">
<ActivityFeedNotifications notifications={this.state.notifications} />
</div>
</div>
</div>
</div>
</>
)
}
A more "React-like" way of doing it could be to replace your entire condition wiht the following :
return (
<>
<Navigation notifications={this.state.notifications} />
{this.state.feedPreference === 1 && <AnnotationSearchForm />}
<div className="activity-feed-container">
<div className="container">
<OnboardingInformation onboarding={this.state.onboardingWelcome} />
<LoadingIndicator loading={this.state.isLoading} />
<div className="row">
{this.state.feedPreference === 1 ?
<>
<div className="col-md-6 col-md-offset-3">
<AnnotationFeed {...this.state} />
</div>
<div className="col-md-1 col-md-offset-1">
<ActivityFeedNotifications notifications={this.state.notifications} />
</div>
</>
:
<div className="col-md-12">
<AnnotationFeed {...this.state} />
</div>
}
<div className="col-md-6 col-md-offset-3">
<AnnotationFeed {...this.state} />
</div>
<div className="col-md-1 col-md-offset-1">
<ActivityFeedNotifications notifications={this.state.notifications} />
</div>
</div>
</div>
</div>
</>
)
Using inline ifs (&&) allows you to avoid repetitions. If you cannot use fragments (<> they were added in the latest React version) you can replace them with <div> tags

Resources