I’m trying to learn Ionic and React I’m combining a Map app and a notes app and having it so I navigate with an IonToolbar.
I have the root go to the map. I click on the Notes app and it goes to the Notes app. When I go back to the Map, nothing shows up although I do see console logs and the url changes. There is also a component that allows you to add to Notes called Add. I can go back and forth between Notes and Add. But I can’t go back to Map. Any help will be appreciated. I’m a beginner so this is probably a basic question but any pointers would be helpful.
Here is my App.js
import { Redirect, Route } from 'react-router-dom';
import { IonApp, IonRouterOutlet, IonTabButton, IonTabBar, IonLabel, IonIcon, IonTabs } from '@ionic/react';
import { IonReactRouter } from '@ionic/react-router';
import Map from './pages/Map';
import Notes from './pages/Notes';
import Add from './pages/Add';
import { triangle, ellipse, square } from 'ionicons/icons';
/* Core CSS required for Ionic components to work properly */
import '@ionic/react/css/core.css';
/* Basic CSS for apps built with Ionic */
import '@ionic/react/css/normalize.css';
import '@ionic/react/css/structure.css';
import '@ionic/react/css/typography.css';
/* Optional CSS utils that can be commented out */
import '@ionic/react/css/padding.css';
import '@ionic/react/css/float-elements.css';
import '@ionic/react/css/text-alignment.css';
import '@ionic/react/css/text-transformation.css';
import '@ionic/react/css/flex-utils.css';
import '@ionic/react/css/display.css';
/* Theme variables */
import './theme/variables.css';
function App () {
return (
<IonApp>
<IonReactRouter>
<IonTabs>
<IonRouterOutlet>
<Route exact path="/map" component={Map}/>
<Route exact path="/notes" component={Notes}/>
<Route exact path="/add" component={Add}/>
<Route exact path = "/" render={() => <Redirect to="/map"/>}/>
</IonRouterOutlet>
<IonTabBar slot='bottom'>
<IonTabButton tab = 'Map' href='/map'>
<IonIcon icon={triangle} />
<IonLabel>Map</IonLabel>
</IonTabButton>
<IonTabButton tab = 'Notes' href='/notes'>
<IonIcon icon={square} />
<IonLabel>Notes</IonLabel>
</IonTabButton>
</IonTabBar>
</IonTabs>
</IonReactRouter>
</IonApp>
);
}
export default App;
Here is my Map.js:
import ReactDOM from 'react-dom'
import React, { useRef, useEffect } from 'react';
import mapboxgl from 'mapbox-gl';
import '../App.css';
import fetchFakeData from '../api/fetchFakeData';
import Popup from '../components/Popup';
mapboxgl.accessToken = process.env.REACT_APP_MAPBOX_ACCESS_TOKEN;
const App = () => {
const mapContainerRef = useRef(null);
const popUpRef = useRef(new mapboxgl.Popup({ offset: 15}));
//initialize map when component mounts
useEffect(() => {
console.log("I'm here")
const map = new mapboxgl.Map({
container: mapContainerRef.current,
// See style options here: https://docs.mapbox.com/api/maps/#styles
style: 'mapbox://styles/mapbox/streets-v11',
center: [-104.9876, 39.7405],
zoom: 12.5,
});
// add navigation control (the +/- zoom buttons)
map.addControl(new mapboxgl.NavigationControl(), 'bottom-right');
map.on('load', () => {
// add the data source for new a feature collection with no features
map.addSource('random-points-data', {
type: 'geojson',
data: {
type: 'FeatureCollection',
features: [],
},
});
// now add the layer, and referece the data source above by name
map.addLayer({
id: 'random-points-layer',
source: 'random-points-data',
type: 'symbol',
layout: {
// full list of icons here: https://labs.mapbox.com/maki-icons
'icon-image': 'bakery-15', //this will put little croissants on our map
'icon-padding':0,
'icon-allow-overlap': true,
},
});
});
map.on('moveend', async () =>{
//get new center coordinates
const { lng, lat } = map.getCenter();
// fetch new data
const results = await fetchFakeData({ longitude: lng, latitude: lat });
// update 'random-points-data' source with new data
// all layers that consume the 'random-points-data' data source will be updated
map.getSource('random-points-data').setData(results);
});
map.on('click', 'random-points-layer', e => {
if (e.features.length) {
const feature = e.features[0];
// create popup node
const popupNode = document.createElement('div');
ReactDOM.render(<Popup feature={feature} />, popupNode);
// set popup on map
popUpRef.current.setLngLat(feature.geometry.coordinates).setDOMContent(popupNode).addTo(map);
}
});
map.on('mouseenter', 'random-points-layer', e => {
if (e.features.length) {
map.getCanvas().style.cursor = 'pointer';
}
});
// reset cursor to default when user is no longer hovering over a clickable feature
map.on('mouseleave', 'random-points-layer', () => {
map.getCanvas().style.cursor = '';
});
// clean up on unmount
return () => map.remove();
}, []); //eslint-disable-line react-hooks/exhaustive-deps
return <div className='map-container' ref={mapContainerRef} />;
};
export default App;
and here is my Notes.js
import { IonButton, IonButtons, IonCard, IonCardContent, IonCardHeader, IonCardSubtitle, IonCheckbox, IonCol, IonContent, IonFab, IonFabButton, IonGrid, IonHeader, IonIcon, IonItem, IonPage, IonRow, IonSlide, IonSlides, IonToolbar } from '@ionic/react';
import styles from './Notes.module.scss';
import { addOutline, menuOutline, notificationsOutline, searchOutline } from "ionicons/icons";
import { getCategories, getNotes } from '../store/Selectors';
import { CategoryStore, NoteStore } from '../store';
import { markNote } from "../store/NoteStore";
const Notes = () => {
const categories = CategoryStore.useState(getCategories);
const notes = NoteStore.useState(getNotes);
const getNoteStyle = (categoryID, isComplete = false) => {
const categoryColor = categories.filter(category => category.id === categoryID)[0].color;
return {
"--background": categoryColor,
"--background-checked": categoryColor,
"--border-style": "none",
"opacity": isComplete ? "0.6" : "1"
}
}
return (
<IonPage>
<IonHeader>
<IonToolbar>
<IonButtons slot="start">
<IonButton>
<IonIcon icon={ menuOutline } />
</IonButton>
</IonButtons>
<IonButtons slot="end">
<IonButton>
<IonIcon icon={ searchOutline } />
</IonButton>
<IonButton>
<IonIcon icon={ notificationsOutline } />
</IonButton>
</IonButtons>
</IonToolbar>
</IonHeader>
<IonContent fullscreen>
<IonGrid>
<IonRow>
<IonCol size="12" className="ion-padding-start">
<h1 className={ styles.mainTitle }>Hello, Alan!</h1>
</IonCol>
</IonRow>
<IonRow>
<IonCol size="12" className="ion-padding-start ion-padding-top">
<IonCardSubtitle className={ styles.heading }>
Categories
</IonCardSubtitle>
</IonCol>
</IonRow>
</IonGrid>
<IonSlides id="slider" options={{ slidesPerView: "auto", zoom: true, grabCursor: true }} className={ `${ styles.categorySlider } ion-padding-bottom` }>
{ categories.map((category, index) => {
const noteCount = notes.filter(n => n.category_id === category.id).length;
return (
<IonSlide key={ `categorySlide_${ index }`}>
<IonCol className="ion-text-left">
<IonCard>
<IonCardHeader className="ion-no-padding">
<div className={ styles.slideCount }>
<h6>{ noteCount } { noteCount === 1 ? "note" : "notes" } </h6>
</div>
<div className={ styles.slideHeader }>
<h4>{ category.name }</h4>
</div>
</IonCardHeader>
<IonCardContent>
<div className={ styles.categoryColor } style={{ borderBottom: `2px solid ${ category.color }` }}></div>
</IonCardContent>
</IonCard>
</IonCol>
</IonSlide>
);
})}
</IonSlides>
<IonGrid className={ styles.bottomContainer }>
<IonRow>
<IonCol size="12" className="ion-padding-start">
<IonCardSubtitle className={ styles.heading }>
Recent Notes
</IonCardSubtitle>
</IonCol>
</IonRow>
<div className={ styles.recentNotes }>
{ notes.map((note, index) => {
return (
<IonRow key={ `note_${ index }` } className="animate__animated animate__faster" id={ `noteRow_${ note.id }` }>
<IonCol size="12">
<IonItem>
<IonCheckbox checked={ note.complete } style={ getNoteStyle(note.category_id, note.complete) } onClick={ () => markNote(note.id) } />
<h4 style={ note.complete ? { textDecoration: "line-through", opacity: "0.6" } : {} }>{ note.note }</h4>
</IonItem>
</IonCol>
</IonRow>
);
})}
</div>
</IonGrid>
<IonFab vertical="bottom" horizontal="end" slot="fixed" className="ion-padding">
<IonFabButton routerLink="/add">
<IonIcon icon={ addOutline } />
</IonFabButton>
</IonFab>
</IonContent>
</IonPage>
);
};
export default Notes;
I hope I’m explaining myself, please let me know if any more of my code needs to be shown. Thanks for reading.
1 post - 1 participant