I have a (Map) component dynamically imported to my page.
const Map = dynamic(() => import('../components/Mapcomp'), { ssr: false, })
From that component I also want to import a variable.
const [taskImg, setTaskImg] = useState(null);
export {taskImg};
The component is dynamically imported because otherwise I get a window is not defined error, and this is the solution for that.
Same with the variable. If I want to import it I get the above error.
But I need to use the taskImg variable in this page.
How can I do that?
Mapcomp:
import { MapContainer, TileLayer, useMap, Marker, Popup,
ImageOverlay } from 'react-leaflet'
import { useEffect, useState } from "react";
import Head from "next/head"
import { LatLngBounds } from 'leaflet';
const Map = () => {
const [userPos, setUserPos] = useState(null)
const [taskPos, setTaskPos] = useState(null)
const [task, setTask] = useState()
const [taskImg, setTaskImg] = useState(null);
const bounds = new LatLngBounds([81.505, -0.09], [50.773941, -84.12544])
useEffect(() => {
function getRandomTask(arr) {
const randomIndex = Math.floor(Math.random() * arr.length);
const item = arr[randomIndex];
return item;
}
const tasks = [
"boller",
"placeholder"
];
setTask(getRandomTask(tasks));
},[])
useEffect(() => {
if(task == "boller"){
console.log("boller")
setTaskImg("/sf2.jpg")
} else if(task == "placeholder") {
console.log("placeholder")
}
},[task])
return (
<>
<Head>
<link rel="stylesheet" href="https://unpkg.com/leaflet#1.5.1/dist/leaflet.css"
integrity="sha512-xwE/Az9zrjBIphAcBb3F6JVqxf46+CDLwfLMHloNu6KEQCAWi6HcDUbeOfBIptF7tcCzusKFjFw2yuvEpDL9wQ=="
crossorigin=""/>
<script src="https://unpkg.com/leaflet#1.5.1/dist/leaflet.js"
integrity="sha512-GffPMF3RvMeYyc1LWMHtK8EbPv0iNZ8/oTtHPx9/cc2ILxQ+u905qIwdpULaqDkyBKgOaB57QTMg7ztg8Jm2Og=="
crossorigin=""></script>
</Head>
<MapContainer
className='absolute h-[750px] w-[750px] left-[45%] top-[80px] bg-no-repeat bg-cover bg-[#738aaf]'
center={[71.505, -40.09]} zoom={3} scrollWheelZoom={true} noWrap={true}>
<ImageOverlay
url="/allmaphres.png"
bounds={bounds}
opacity={1}
zIndex={10}
/>
</MapContainer>
</>
);
}
export default Map;
page (mapcomp is rendered here):
import { memo, useEffect, useMemo, useState } from "react";
import dynamic from 'next/dynamic'
import Navbar from "../components/Navbar";
import Footer from "../components/Footer";
import Head from "next/head";
const Map = dynamic(() => import('../components/Mapcomp'), {
ssr: false,
})
const All = () => {
return (
<>
<Navbar />
<div className="bg-white w-[500px] h-[100vh]">
<div className="task border-4 border-red-500 h-[250px]">
{/* taskImg && <img src={taskImg}/> */}
</div>
<div className="flex justify-center gap-[200px] text-xl">
<span>Tasks:</span>
<span>Points:</span>
</div>
<div className="flex justify-center gap-[240px] text-xl">
<span>X</span>
<span>X</span>
</div>
</div>
<Map />
<Footer />
</>
);
}
export default All;
You can't export a state to another component you either need to use a state management library like redux or create a context which make the state available for all the other components
Related
I have a hamburger component that has no className prop, only color, and using the ternary operator its color changes only after page reload, but for example FontAwesomeIcon using dark:text-gray-50 changes its color.
This is my TodoHeader.jsx component
import Search from "./Search";
import Switcher from "../Switcher";
import {faBars} from "#fortawesome/free-solid-svg-icons";
import {FontAwesomeIcon} from "#fortawesome/react-fontawesome";
import {Fade as Hamburger} from "hamburger-react";
import {useProSidebar} from "react-pro-sidebar";
import useDarkSide from "../../hooks/useDarkSide";
const TodoHeader = () => {
const {collapseSidebar} = useProSidebar();
const [colorTheme, setTheme] = useDarkSide();
const toggle = () => {
collapseSidebar()
}
return (
<div className={"flex items-center justify-between border-b-2 dark:border-gray-600"}>
<div className={"flex items-center ml-8"}>
<Hamburger direction={"right"} onToggle={toggle} color={ colorTheme === 'light' ? "#f3f4f6" : "#1f2937"}/>
<FontAwesomeIcon icon={faBars} onClick={toggle} className={"text-center dark:text-gray-50"}/>
<h1 className={"p-4 text-2xl text-gray-800 dark:text-gray-100"}>Todo List</h1>
</div>
<Search/>
<Switcher/>
</div>
);
};
export default TodoHeader;
This is my customhook
import {useEffect, useMemo, useState} from "react";
const useDarkSide = () => {
const [theme, setTheme] = useState(localStorage.theme);
const colorTheme = theme === "dark" ? "light" : "dark";
useEffect(() => {
const root = window.document.documentElement;
root.classList.remove(colorTheme);
root.classList.add(theme);
localStorage.setItem('theme', theme);
}, [theme, colorTheme]);
return [colorTheme, setTheme]
}
export default useDarkSide
And this is Switcher.jsx component that handles dark/light mode changes
import {useState} from "react";
import { DarkModeSwitch} from "react-toggle-dark-mode";
import useDarkSide from "../hooks/useDarkSide";
const Switcher = () => {
const [colorTheme, setTheme] = useDarkSide();
const [darkSide, setDarkSide] = useState(
colorTheme === "light" ? true : false
);
const toggleDarkMode = (checked) => {
setTheme(colorTheme);
setDarkSide(checked);
};
return (
<>
<DarkModeSwitch
style={{ marginRight: '2rem' }}
checked={darkSide}
onChange={toggleDarkMode}
size={30}
/>
</>
);
}
export default Switcher
I think the problem is that when I use the useDarkSide hook on the header it doesn't render the header component, but I don't know how to make it work
So, the problem was with me trying to access theme state that was inside switcher component through useDarkSide custom hook, but it's create another separated state. So the solution was using global state, in my case i used redux.
I am using leaflet, javascript, and react. The leaflet has a plugin called Leaflet sync.
This plugin sync two or more map demo. I want to synchronize the map in two different browsers' tabs. Leaflet sync does not work in two different tabs. Here is my code so far Code Link.
import React, { useEffect } from "react";
import L, { LatLngTuple } from "leaflet";
import { FC, useState } from "react";
import { MapContainer } from "react-leaflet";
import "./styles.css";
// import "leaflet.sync";
import MapContent from "./MapContent";
import styled from "styled-components";
import { Link, HashRouter as Router, Routes, Route } from "react-router-dom";
import MapOne from "./MapOne";
import MapTwo from "./MapTwo";
export default function App() {
const [center] = useState<LatLngTuple>([0, 0]);
const [bounds] = useState([
[432205, 6475078],
[437720, 6481113]
]);
const [zoom] = useState(0);
const [loaded, setLoaded] = useState(false);
const [mapA, setMapA] = useState<any>();
const [mapB, setMapB] = useState<any>();
return (
<Router>
<div style={{ display: "flex", flexDirection: "column" }}>
<Link to="/mapone" target="_blank">
Open Map One
</Link>
<Link to="/maptwo" target="_blank">
Open Map Two
</Link>
</div>
<Routes>
<Route exact path="/mapone" element={<MapOne />} />
<Route exact path="/maptwo" element={<MapTwo />} />
</Routes>
</Router>
);
}
// MapOne.tsx
export default function MapOne() {
const [center] = useState<LatLngTuple>([0, 0]);
const [bounds] = useState([
[432205, 6475078],
[437720, 6481113]
]);
const [zoom] = useState(0);
const [loaded, setLoaded] = useState(false);
const [mapA, setMapA] = useState<any>();
const [mapB, setMapB] = useState<any>();
useEffect(() => {
if (mapA) {
mapA.fitBounds(bounds);
}
// This does not work since mapB exist in another tab
// if (mapA && mapB) {
// mapA.sync(mapB);
// mapB.sync(mapA);
// mapA.fitBounds(bounds);
// }
}, [mapA, mapB, bounds]);
return (
<StyledDiv>
<h1>Map One</h1>
<MapContainer
whenReady={() => setLoaded(true)}
whenCreated={setMapA}
center={center}
zoom={zoom}
scrollWheelZoom={true}
placeholder={<MapPlaceholder />}
crs={L.CRS.Simple}
minZoom={-4}
>
<MapContent loaded={loaded} bounds={bounds} />
</MapContainer>
</StyledDiv>
);
}
// MapTwo.tsx
export default function MapTwo() {
const [center] = useState<LatLngTuple>([0, 0]);
const [bounds] = useState([
[432205, 6475078],
[437720, 6481113]
]);
const [zoom] = useState(0);
const [loaded, setLoaded] = useState(false);
const [mapA, setMapA] = useState<any>();
const [mapB, setMapB] = useState<any>();
useEffect(() => {
if (mapB) {
mapB.fitBounds(bounds);
}
// if (mapA && mapB) {
// mapA.sync(mapB);
// mapB.sync(mapA);
// mapA.fitBounds(bounds);
// }
}, [mapA, mapB, bounds]);
return (
<StyledDiv>
<h1>Map Two</h1>
<MapContainer
whenReady={() => setLoaded(true)}
whenCreated={setMapB}
center={center}
zoom={zoom}
scrollWheelZoom={true}
placeholder={<MapPlaceholder />}
crs={L.CRS.Simple}
minZoom={-4}
>
<MapContent loaded={loaded} bounds={bounds} />
</MapContainer>
</StyledDiv>
);
}
How can I use mapA.sync(mapB) to sync maps in two different browsers' tabs. I think I cannot since both are isolated from each other.
How can I achieve the same functionality as in leaflet sync but with different browser tabs?
I have seen this asked before but I can't seem to be able to wrap my head around it with my situation.
I am using a search bar to filter the data down and it works but the image will not update. The URL passing to the child works fine but it's just not changing its state. I just don't really understand how to implement it.
PokemonList.jsx
import axios from "axios";
import React, { useEffect, useState } from "react";
import PokemonSprite from "./PokemonSprite";
import Card from "#material-tailwind/react/Card";
import CardBody from "#material-tailwind/react/CardBody";
import CardFooter from "#material-tailwind/react/CardFooter";
import H6 from "#material-tailwind/react/Heading6";
import Paragraph from "#material-tailwind/react/Paragraph";
import Button from "#material-tailwind/react/Button";
// const baseURL = "https://pokeapi.co/api/v2/pokemon?limit=898";
const baseURL = "https://pokeapi.co/api/v2/pokemon?limit=20";
export default function PokemonList() {
const [post, setPost] = useState([]);
const [searchTerm, setSearchTerm] = useState('');
useEffect(() => {
axios.get(baseURL).then((response) => {
setPost(response.data.results);
});
}, []);
if (!post) return <p>Sorry, no results.</p>;
return (
<div>
<input type="text" placeholder="Search..." onChange={e => {setSearchTerm(e.target.value)}}/>
{post.filter((data) => {
if (searchTerm == "") {
return data;
} else if (data.name.toLowerCase().includes(searchTerm.toLowerCase())) {
console.log(data);
return data;
}
}).map((data, idx) => (
<div className="p-5">
<Card key={idx}>
<PokemonSprite url={data.url} />
<CardBody>
<H6 color="gray">{data.name}</H6>
<Paragraph color="gray">
Don't be scared of the truth because we need to restart the human
foundation in truth And I love you like Kanye loves Kanye I love
Rick Owens’ bed design but the back is...
</Paragraph>
</CardBody>
<CardFooter>
<Button color="lightBlue" size="lg" ripple="light">
Read More
</Button>
</CardFooter>
</Card>
</div>
))}
</div>
);
}
PokemonSprite.jsx
import axios from "axios";
import React, { useEffect, useState } from "react";
import CardImage from "#material-tailwind/react/CardImage";
export default function PokemonList(url) {
const [post, setPost] = useState();
console.log(url);
useEffect(() => {
axios.get(url.url).then((response) => {
//console.log(response.data);
setPost(response.data);
});
}, []);
if (!post) return <p>Sorry, no results.</p>;
return (
<div>
<CardImage
src={post.sprites.front_default}
alt="Card Image"
/>
</div>
);
}
Please rewrite your PokemonSprite component like this to enable re rendering on updates to the Url...
import axios from "axios";
import React, { useEffect, useState } from "react";
import CardImage from "#material-tailwind/react/CardImage";
export default function PokemonList(url) {
const [post, setPost] = useState();
console.log(url);
const getUpdatedImage = async (imageUrl) => {
const response = await axios.get(imageUrl);
setPost(response.data);
return post;
}
useEffect(() => {
getUpdatedImage(url.url);
}, [url]);
if (!post) return <p>Sorry, no results.</p>;
return (
<div>
<CardImage
src={post.sprites.front_default}
alt="Card Image"
/>
</div>
);
}
This is my PopBlock.jsx file where i have my button in and i need to be able to click the button and open the popup where all the information is another file Popup.jsx how could i make this pop up work
import React, {useContext, useEffect, useState} from 'react';
import PropTypes from 'prop-types';
import styles from './PopupBlock.module.scss';
import {getImageProps, getValue} from '../../../utils';
import {ServiceContext} from '../../Services';
import Popup from './Popup';
const PopupBlock = ({block}) => {
const services = useContext(ServiceContext);
const [imageProps, setImageProps] = useState(null);
const [open, setOpen] = useState(false);
useEffect(() => {
if (block) {
setImageProps(getImageProps(
block.image,
null,
url => services.content.getFileURL(url)
));
} else {
setImageProps(null);
}
}, [block, services]);
return (
<div className={styles.container}>
<div className={styles.content}>
{getValue(block.title, null, (title) => (<h3>{title}</h3>))}
{getValue(block.text, null, (text) =>
(<button onClick={() => setOpen(true)}>{text}</button>))}
</div>
{imageProps ? (
<div className={styles.image}>
<img alt="Alt text populated from Acoustic" {...imageProps} />
</div>
) : null}
<div className={[styles.popup, /*styles.visible*/].join(' ')}>
<Popup block={block}/>
</div>
</div>
);
}
;
PopupBlock.propTypes =
{
block: PropTypes.object
}
;
export default PopupBlock;
This is my Popup.jsx file where the inner information of the pop up is
import React, {useContext, useEffect, useState} from 'react';
import PropTypes from 'prop-types';
import styles from './Popup.module.scss';
import {getImageProps, getValue} from '../../../utils';
import {ServiceContext} from '../../Services';
import Html from '../../Html';
const Popup = ({block}) => {
const services = useContext(ServiceContext);
const [imageProps, setImageProps] = useState(null);
useEffect(() => {
if (block) {
setImageProps(getImageProps(
block.image,
null,
url => services.content.getFileURL(url)
));
} else {
setImageProps(null);
}
}, [block, services]);
return (
<div className={styles.background}>
<div className={styles.container}>
{imageProps ? (
<div className={styles.image}>
<img alt="Alt text populated from Acoustic" {...imageProps} />
</div>
) : null}
<div className={styles.content}>
<div className={styles.section}>
{getValue(block.title, null, (title) => (<h3>{title}</h3>))}
{getValue(block.content, null, (content) => (<Html value={content}/>))}
</div>
<div className={styles.info}>
{getValue(block.information, null, (information) => (<Html value={information}/>))}
</div>
</div>
</div>
</div>
);
}
;
Popup.propTypes =
{
block: PropTypes.object
}
;
export default Popup;
if anyone knows how i could make a pop up for this please let me know thanks the blocks are what have the button on and when they are pressed i want the pop up with all the information in to come up
I have a lot of globally declared states in my application. I used useContext for implementing it, however, I keep getting a bunch of errors in the console regarding useContext.
Error:
Warning: useContext() second argument is reserved for future use in React. Passing it is not supported. You passed: false.
in Navbar (at Home.js:11)
in Home (created by Context.Consumer)
in Route (at App.js:96)
in Switch (at App.js:76)
in Router (created by BrowserRouter)
in BrowserRouter (at App.js:74)
in App (at src/index.js:7)
in StrictMode (at src/index.js:6)
App.js:
import React, { useState, useEffect } from 'react';
import { Redirect } from 'react-router-dom';
import './App.css';
import Home from '../pages/Home';
import { BrowserRouter as Router, Switch, Route } from 'react-router-dom';
import Restaurants from '../pages/Restaurants';
import ScrollToTop from '../components/ScrollToTop';
import UserAccount from '../pages/UserAccount'
import Footer from '../components/footer/Footer';
import { UserContext } from '../UserContext';
function App() {
const [clickedDistrict, setClickedDistrict] = useState(false);
const [clickedSuggestion, setClickedSuggestion] = useState(false);
const [checkedDistance, setCheckedDistance] = useState("1000")
const [restaurants, setRestaurants] = useState([]);
const [clickedUserMenuItem, setClickedUserMenuItem]
= useState("saved")
const [goodPassword, setGoodPassword] = useState(false)
const [chosenRestaurant, setChosenRestaurant] = useState(false);
const [generalSearchPath, setGeneralSearchPath] = useState(false);
const [incorrectPassword, setIncorrectPassword] = useState(false);
const [successfullLogin, setSuccessfullLogin] = useState(false)
const [username, setUsername] = useState(false)
const [incorrectOldPassword, setIncorrectOldPassword] = useState(false)
const [logout, setLogout] = useState(false);
const [newUsername, setNewUsername] = useState(false)
const [incorrectPasswordOnDelete, setIncorrectPasswordOnDelete] = useState(false)
const [deleteAccount, setDeleteAccount ] = useState(false)
return (
<>
<Router>
<ScrollToTop />
<Switch>
<UserContext.Provider value={{
clickedDistrict, setClickedDistrict,
clickedSuggestion, setClickedSuggestion,
checkedDistance, setCheckedDistance,
restaurants, setRestaurants,
clickedUserMenuItem, setClickedUserMenuItem,
goodPassword, setGoodPassword,
chosenRestaurant, setChosenRestaurant,
generalSearchPath, setGeneralSearchPath,
incorrectPassword, setIncorrectPassword,
successfullLogin, setSuccessfullLogin,
username, setUsername,
incorrectOldPassword, setIncorrectOldPassword,
logout, setLogout,
newUsername, setNewUsername,
incorrectPasswordOnDelete, setIncorrectPasswordOnDelete,
deleteAccount, setDeleteAccount
}}>
<Route path='/' exact component={Home} />
<Route path='/restaurants' component={Restaurants} />
{ (successfullLogin && !logout && !deleteAccount) ?
<Route path='/user' component={UserAccount} />
:
<>
<Route path='/user' component={UserAccount} />
<Redirect to='/' /></>
}
</UserContext.Provider>
</Switch>
<Footer />
</Router>
</>
);
}
export default App;
UserContext.js:
import { createContext } from "react";
export const UserContext = createContext();
I tried searching about this warning but nothing helped. I don't even understand the reason for this error. Which second argument does it imply?
Also, the weird thing is that I have theese states used throughout the application, but the error shows that I have a problem in the navbar on the Home page.
Home:
import React from 'react';
import Cards from '../components/cards/Cards';
import HeroSection from '../components/hero/HeroSection';
import Districts from '../components/districts/Districts';
import Navbar from '../components/navbar/Navbar';
import CollegeSection from '../components/college/CollegeSection';
function Home() {
return (
<>
<Navbar />
<HeroSection />
<Cards />
<CollegeSection />
<Districts />
</>
);
}
export default Home;
import React, { useEffect, useContext } from 'react';
import { Button } from '../button/Button';
import MobileNavbar from './MobileNavbar'
import { Link } from 'react-router-dom';
import './Navbar.css';
import { Modal } from '../forms/Modal'
import Searchbox from '../search/Searchbox';
import NavbarLogic from './NavbarLogic';
import { UserContext } from '../../UserContext';
import UserNavbar from '../user/UserNavbar';
function Navbar() {
const { click, button, showButton,
handleClick, closeMenuDiscardChanges, closeMenuOpenPCRestaurants }
= MobileNavbar();
const { navMenuClassName, searchbox, showLogInModal,
showSignUpModal, openLogInModal, openSignUpModal,
setShowLogInModal, setShowSignUpModal }
= NavbarLogic();
const { successfullLogin, setSuccessfullLogin, logout }
= useContext(UserContext);
useEffect(() => {
showButton();
}, [showButton]);
useEffect(() => {
if (logout) {
setShowLogInModal(false);
setSuccessfullLogin(false)
}
}, [logout,setSuccessfullLogin,setShowLogInModal])
window.addEventListener('resize', showButton);
return (
<>
<nav className={click ? 'navbar active' : 'navbar'}>
<div className='navbar-container'>
<Link to='/' className='navbar-logo' onClick={closeMenuDiscardChanges}>
Restaurateur<i class="fas fa-utensils" />
</Link>
<div className={click ? 'hidden' : searchbox}>
<Searchbox />
</div>
<div className='menu-icon' onClick={handleClick}>
<i className={click ? 'fas fa-times' : 'fas fa-bars'} />
</div>
<ul className={click ? 'nav-menu active' : navMenuClassName}>
<li className='nav-item'>
<Link to='/' className='nav-links' onClick={closeMenuDiscardChanges}>
Home
</Link>
</li>
<li className='nav-item'>
<Link
to='/restaurants'
className='nav-links'
onClick={setRestaurantsNavLink() === "All Restaurants" ?
closeMenuDiscardChanges
:
closeMenuOpenPCRestaurants}
>
{setRestaurantsNavLink()}
</Link>
</li>
<li>
<Link
className='nav-links-mobile'
onClick={openLogInModal}
>
Log In
</Link>
<Link
className='nav-links-mobile'
onClick={openSignUpModal}
>
Sign Up
</Link>
</li>
</ul>
{successfullLogin === true ?
<UserNavbar />
:
<>
{button &&
<Button
buttonStyle='btn--outline'
buttonSize='btn--medium'
onClick={openLogInModal}
id="login">
LOG IN
</Button>}
<Modal
showLogInModal={showLogInModal}
setShowLogInModal={setShowLogInModal}
/>
{button &&
<Button
id="signup"
buttonSize='btn--medium'
onClick={openSignUpModal}>
SIGN UP
</Button>}
<Modal
showSignUpModal={showSignUpModal}
setShowSignUpModal={setShowSignUpModal}
/>
</>}
</div>
</nav>
</>
);
}
export default Navbar;
How can I get rid of this useContext warning?
Edit:
This is how I use useContext in Mobilenavbar:
import { useState, useContext } from 'react';
import { UserContext } from "../../UserContext"
const MobileNavbar = () => {
const [click, setClick] = useState(false);
const [button, setButton] = useState(true);
const { setPragueCollegePath } = useContext(UserContext)
const { setClickedDistrict, setClickedSuggestion } = useContext(UserContext)
const { setChosenRestaurant, setGeneralSearchPath } = useContext(UserContext);
const handleClick = () => setClick(!click);
const closeMenuOpenRestaurants = () => {
setClick(false);
setClickedDistrict(false);
setClickedSuggestion(false);
setChosenRestaurant(false);
setGeneralSearchPath(false)
}
const closeMenuOpenPCRestaurants = () => {
setClick(false);
setClickedDistrict(false);
setClickedSuggestion(false);
setChosenRestaurant(false);
setGeneralSearchPath(false);
}
const closeMenuDiscardChanges = () => {
setClick(false);
setClickedDistrict(false)
setClickedSuggestion(false)
setChosenRestaurant(false)
setGeneralSearchPath(false);
}
const showButton = () => {
if (window.innerWidth <= 1120) {
setButton(false);
} else {
setButton(true);
}
};
const showSearch = () => {
if (window.innerWidth <= 820) {
setButton(false);
} else {
setButton(true);
}
};
return {
click, button, showButton, handleClick,
showSearch, closeMenuOpenRestaurants,
closeMenuOpenPCRestaurants, closeMenuDiscardChanges
}
}
export default MobileNavbar;
And here is NavbarLogic:
const {successfullLogin, setSuccessfullLogin, logout }
= useContext(UserContext);
I usually import all the variables together.