Implement state in URL

This commit is contained in:
Quantum 2022-02-12 16:25:44 -05:00
parent 05236fff14
commit d366604665

View file

@ -1,16 +1,78 @@
import React, {useState} from 'react'; import React from 'react';
import './App.css'; import './App.css';
import {Calendar} from './Calendar'; import {Calendar} from './Calendar';
import {gregorianJDN, Month} from "./dates"; import {gregorianJDN, Month} from "./dates";
function App() { type YearMonth = {
const today = new Date(); year: number;
const todayJDN = gregorianJDN(today.getFullYear(), today.getMonth() + 1, today.getDay()); month: Month;
const [yearMonth, setYearMonth] = useState([230, 5]); }
return (
<Calendar year={yearMonth[0]} month={yearMonth[1] as Month} todayJDN={todayJDN} function parseURL(): YearMonth | null {
onSwitch={(year, month) => setYearMonth([year, month])}/> const match = /\/(-?\d+)\/(\d+)/.exec(window.location.pathname);
); if (!match)
return null;
const month = +match[2];
if (month < 1 || month > 13)
return null;
return {year: +match[1], month: month as Month};
}
type AppState = YearMonth & {
todayJDN: number,
};
class App extends React.Component<{}, AppState> {
state: AppState;
constructor(props: {}) {
super(props);
const current = {year: 230, month: 5};
const today = new Date();
this.state = {
...(parseURL() || current as YearMonth),
todayJDN: gregorianJDN(today.getFullYear(), today.getMonth() + 1, today.getDay()),
};
this.updateURL();
this.updateStateFromURL = this.updateStateFromURL.bind(this);
}
componentDidMount() {
window.addEventListener('popstate', this.updateStateFromURL);
}
componentWillUnmount() {
window.removeEventListener('popstate', this.updateStateFromURL);
}
private updateStateFromURL(event: PopStateEvent) {
this.setState(event.state);
}
private updateURL() {
const {year, month} = this.state;
const path = `/${year}/${month}`;
if (path !== window.location.pathname) {
window.history.pushState({year, month}, '', path);
}
}
setState(state: any, callback?: () => void) {
super.setState(state, () => {
this.updateURL();
callback && callback();
});
}
render() {
return <Calendar
year={this.state.year} month={this.state.month} todayJDN={this.state.todayJDN}
onSwitch={(year, month) => {
this.setState({year, month})
}}/>;
}
} }
export default App; export default App;