Skip to content

Commit

Permalink
Replace recoil for jotai and nuqs (#50)
Browse files Browse the repository at this point in the history
* Replace recoil for jotai and nuqs

* Fix default interactive maps value

* Add apng layer fix
  • Loading branch information
barbara-chaves authored Feb 27, 2024
1 parent 9bfe7e0 commit ea6323f
Show file tree
Hide file tree
Showing 41 changed files with 262 additions and 595 deletions.
4 changes: 2 additions & 2 deletions client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,18 +50,18 @@
"eslint": "8.42.0",
"eslint-config-next": "13.4.5",
"framer-motion": "^10.16.4",
"jotai": "^2.6.4",
"lucide-react": "^0.252.0",
"mapbox-gl": "^3.0.1",
"next": "13.4.5",
"nuqs": "^1.16.1",
"postcss": "8.4.24",
"react": "18.2.0",
"react-chartjs-2": "^5.2.0",
"react-dom": "18.2.0",
"react-hook-form": "^7.45.0",
"react-map-gl": "7.1.5",
"react-markdown": "8.0.7",
"recoil": "^0.7.7",
"recoil-sync": "^0.2.0",
"rooks": "7.14.1",
"tailwind-merge": "^1.13.2",
"tailwindcss": "3.3.2",
Expand Down
28 changes: 3 additions & 25 deletions client/src/app/(landing)/layout-providers.tsx
Original file line number Diff line number Diff line change
@@ -1,38 +1,16 @@
'use client';

import { PropsWithChildren, useCallback } from 'react';
import { PropsWithChildren } from 'react';

import { MapProvider } from 'react-map-gl';

import { RecoilRoot } from 'recoil';

import { RecoilURLSyncNext } from '@/lib/recoil';
import type { Deserialize, Serialize } from '@/lib/recoil';
import RecoilDevTools from '@/lib/recoil/devtools';
import { Provider } from 'jotai';

export default function Providers({ children }: PropsWithChildren) {
const serialize: Serialize = useCallback((x) => {
return x === undefined ? '' : JSON.stringify(x);
}, []);

//Demo of custom deserialization
const deserialize: Deserialize = useCallback((x: string) => {
return JSON.parse(x);
}, []);

return (
<>
<MapProvider>
<RecoilRoot>
<RecoilURLSyncNext
location={{ part: 'queryParams' }}
serialize={serialize}
deserialize={deserialize}
>
<RecoilDevTools />
{children}
</RecoilURLSyncNext>
</RecoilRoot>
<Provider>{children}</Provider>
</MapProvider>
</>
);
Expand Down
4 changes: 2 additions & 2 deletions client/src/app/(static)/layout-providers.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@

import { PropsWithChildren } from 'react';

import { RecoilRoot } from 'recoil';
import { Provider } from 'jotai';

export default function Providers({ children }: PropsWithChildren) {
return (
<>
<RecoilRoot>{children}</RecoilRoot>
<Provider>{children}</Provider>
</>
);
}
2 changes: 1 addition & 1 deletion client/src/components/map/layers/animated-tile/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ export class AnimatedTile {
image: FRAME.bitmapData,
bounds: [west, south, east, north],
getPolygonOffset: () => {
return [0, 20000];
return [0, 100000];
},
zoom,
visible,
Expand Down
8 changes: 4 additions & 4 deletions client/src/components/map/legend/item-types/switch/index.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
import { useCallback, useMemo } from 'react';

import { useRecoilValue, useSetRecoilState } from 'recoil';
import { useAtomValue, useSetAtom } from 'jotai';

import { layersSettingsAtom } from '@/store';
import { layersSettingsAtom } from '@/store/map';

import { Switch } from '@/components/ui/switch';

import { LegendTypeSwitchProps } from '../../types';

const LegendTypeSwitch = ({ layerId, param, layerTitle }: LegendTypeSwitchProps) => {
const layersSettings = useRecoilValue(layersSettingsAtom);
const layersSettings = useAtomValue(layersSettingsAtom);
const checked = useMemo(() => layersSettings[layerId]?.[param], [layerId, layersSettings, param]);

const setLayersSettings = useSetRecoilState(layersSettingsAtom);
const setLayersSettings = useSetAtom(layersSettingsAtom);

const handleChangeVisibility = useCallback(
(checked: boolean) => {
Expand Down
10 changes: 5 additions & 5 deletions client/src/components/map/legend/item-types/timeline/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'

import { Root, Track, Thumb } from '@radix-ui/react-slider';
import { PauseIcon, PlayIcon } from 'lucide-react';
import { useRecoilValue, useSetRecoilState } from 'recoil';
import { useAtomValue, useSetAtom } from 'jotai';

import { layersSettingsAtom, timelineAtom } from '@/store';
import { layersSettingsAtom, timelineAtom } from '@/store/map';

import { LegendTypeTimelineProps } from '@/components/map/legend/types';
import { Button } from '@/components/ui/button';
Expand All @@ -24,12 +24,12 @@ export const LegendTypeTimeline: React.FC<LegendTypeTimelineProps> = ({
const textMarginX = 16;
const intervalRef = useRef<NodeJS.Timer>();

const setLayersSettings = useSetRecoilState(layersSettingsAtom);
const setLayersSettings = useSetAtom(layersSettingsAtom);

const [isPlaying, setIsPlaying] = useState(false);

const timelines = useRecoilValue(timelineAtom);
const setTimelines = useSetRecoilState(timelineAtom);
const timelines = useAtomValue(timelineAtom);
const setTimelines = useSetAtom(timelineAtom);

const frame = useMemo(() => timelines[id]?.frame || 0, [id, timelines]);

Expand Down
10 changes: 4 additions & 6 deletions client/src/containers/home/categories/item.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import { useRecoilState, useResetRecoilState } from 'recoil';

import { cn } from '@/lib/classnames';

import { categoryAtom } from '@/store/home';
import { useSyncCategory } from '@/store/home';

import { Category } from '@/types/generated/strapi.schemas';

Expand All @@ -13,12 +11,12 @@ import { TooltipTrigger, TooltipContent, Tooltip } from '@/components/ui/tooltip
type CategoryProps = Pick<Category, 'name' | 'slug'>;

const Category = ({ name, slug }: CategoryProps) => {
const [category, setCategory] = useRecoilState(categoryAtom);
const resetCategory = useResetRecoilState(categoryAtom);
const [category, setCategory] = useSyncCategory();

const handleClick = (slug: string) => {
if (category === slug) {
return resetCategory();
setCategory(null);
return;
}
setCategory(slug);
};
Expand Down
8 changes: 4 additions & 4 deletions client/src/containers/home/datasets/layers/item.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
'use client';

import { useRecoilValue, useSetRecoilState } from 'recoil';
import { useAtomValue, useSetAtom } from 'jotai';

import { layersAtom } from '@/store';
import { layersAtom } from '@/store/map';

import { LayerListResponseDataItem } from '@/types/generated/strapi.schemas';

import { Switch } from '@/components/ui/switch';

export default function LayersItem({ id, attributes }: Required<LayerListResponseDataItem>) {
const layers = useRecoilValue(layersAtom);
const setLayers = useSetRecoilState(layersAtom);
const layers = useAtomValue(layersAtom);
const setLayers = useSetAtom(layersAtom);

const handleLayerChange = () => {
if (!id) return;
Expand Down
8 changes: 4 additions & 4 deletions client/src/containers/home/filters/index.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
import { useAtom } from 'jotai';
import { XIcon } from 'lucide-react';
import { useRecoilState } from 'recoil';

import { cn } from '@/lib/classnames';

import { FilterName, filtersOpenAtom } from '@/store/home';
import { filtersOpenAtom } from '@/store/home';

import { Button } from '@/components/ui/button';

import FilterItem from './item';

const filtersData: {
title: string;
id: FilterName;
id: string;
options: { name: string; id: string }[];
}[] = [
{
Expand Down Expand Up @@ -48,7 +48,7 @@ const filtersData: {
];

export const Filters = () => {
const [isOpen, setIsOpen] = useRecoilState(filtersOpenAtom);
const [isOpen, setIsOpen] = useAtom(filtersOpenAtom);

return (
<div
Expand Down
28 changes: 14 additions & 14 deletions client/src/containers/home/filters/item.tsx
Original file line number Diff line number Diff line change
@@ -1,36 +1,36 @@
import { useRecoilState, useResetRecoilState } from 'recoil';

import { FilterName, filterSelector } from '@/store/home';
import { useSyncFilters } from '@/store/home';

import { Button } from '@/components/ui/button';
import { CheckboxButton } from '@/components/ui/checkbox-button';

type FilterItemProps = {
filter: {
title: string;
id: FilterName;
id: string;
options: { name: string; id: string }[];
};
};

const FilterItem = ({ filter: { id, options, title } }: FilterItemProps) => {
const [filter, setFilter] = useRecoilState(filterSelector(id));
const resetFilter = useResetRecoilState(filterSelector(id));
const [filters, setFilters] = useSyncFilters();

const filter = filters[id as keyof typeof filters];

const setFilter = (value: string[] | null) => setFilters({ ...filters, [id]: value });

const handleChangeFilter = (id: string) => {
setFilter((prev) => {
if (!prev.includes(id)) {
return [...prev, id];
}
return prev.filter((item) => item !== id);
});
if (!filter?.includes(id)) {
setFilter([...(filter || []), id]);
} else {
setFilter(filter?.filter((item) => item !== id) || null);
}
};

return (
<div key={id} className="space-y-4">
<div className="flex items-center justify-between">
<h3 className="text-sm font-bold uppercase tracking-widest text-gray-200">{title}</h3>
<Button size="sm" variant="link" onClick={resetFilter}>
<Button size="sm" variant="link" onClick={() => setFilter(null)}>
Unselect all
</Button>
</div>
Expand All @@ -39,7 +39,7 @@ const FilterItem = ({ filter: { id, options, title } }: FilterItemProps) => {
return (
<CheckboxButton
key={optionId}
checked={filter.includes(optionId)}
checked={filter?.includes(optionId)}
value={id}
onCheckedChange={() => handleChangeFilter(optionId)}
label={name}
Expand Down
4 changes: 2 additions & 2 deletions client/src/containers/home/header/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,16 @@

import Image from 'next/image';

import { useAtom } from 'jotai';
import { FilterIcon } from 'lucide-react';
import { useRecoilState } from 'recoil';

import { filtersOpenAtom } from '@/store/home';

import { Button } from '@/components/ui/button';
import GradientLine from '@/components/ui/gradient-line';

const Header = () => {
const [open, setOpen] = useRecoilState(filtersOpenAtom);
const [open, setOpen] = useAtom(filtersOpenAtom);

const handleClickFilters = () => {
setOpen(!open);
Expand Down
17 changes: 8 additions & 9 deletions client/src/containers/home/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,10 @@

import { useEffect } from 'react';

import { useResetRecoilState, useSetRecoilState } from 'recoil';
import { useSetAtom } from 'jotai';

import { layersAtom, tmpBboxAtom } from '@/store';

import { stepAtom } from '@/store/stories';
import { layersAtom, tmpBboxAtom } from '@/store/map';
import { useSyncStep } from '@/store/stories';

import { DEFAULT_MAP_BBOX, DEFAULT_MAP_STATE } from '@/constants/map';

Expand All @@ -22,18 +21,18 @@ import Header from './header';
import TopStories from './top-stories';

export default function Home() {
const setTmpBbox = useSetRecoilState(tmpBboxAtom);
const resetLayers = useResetRecoilState(layersAtom);
const resetStep = useResetRecoilState(stepAtom);
const setTmpBbox = useSetAtom(tmpBboxAtom);
const setLayers = useSetAtom(layersAtom);
const { removeStep } = useSyncStep();

useEffect(() => {
const tmpbbox: [number, number, number, number] = DEFAULT_MAP_BBOX;
setTmpBbox({ bbox: tmpbbox, options: DEFAULT_MAP_STATE });
}, [setTmpBbox]);

useEffect(() => {
resetLayers();
resetStep();
setLayers([]);
removeStep();
}, []);

return (
Expand Down
6 changes: 3 additions & 3 deletions client/src/containers/home/sidebar/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@

import { PropsWithChildren } from 'react';

import { useRecoilValue } from 'recoil';
import { useAtomValue } from 'jotai';

import { cn } from '@/lib/classnames';

import { sidebarOpenAtom } from '@/store';
import { sidebarOpenAtom } from '@/store/map';

export default function Sidebar({ children }: PropsWithChildren) {
const open = useRecoilValue(sidebarOpenAtom);
const open = useAtomValue(sidebarOpenAtom);

return (
<div
Expand Down
7 changes: 0 additions & 7 deletions client/src/containers/home/sync-store.tsx

This file was deleted.

16 changes: 8 additions & 8 deletions client/src/containers/map/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ import dynamic from 'next/dynamic';
import { usePathname } from 'next/navigation';
import { useRouter } from 'next/navigation';

import { useAtomValue, useSetAtom } from 'jotai';
import { LngLatBoundsLike } from 'mapbox-gl';
import { useRecoilValue, useSetRecoilState } from 'recoil';

import { cn } from '@/lib/classnames';

Expand All @@ -19,7 +19,7 @@ import {
layersInteractiveIdsAtom,
// popupAtom,
tmpBboxAtom,
} from '@/store';
} from '@/store/map';

// import { useGetLayers } from '@/types/generated/layer';
// import type { LayerTyped } from '@/types/layers';
Expand Down Expand Up @@ -74,14 +74,14 @@ export default function MapContainer() {

const [marker, setMarker] = useState<GeoJSON.Feature<GeoJSON.Point> | null>(null);

const bbox = useRecoilValue(bboxAtom);
const tmpBbox = useRecoilValue(tmpBboxAtom);
// const isFlyingBack = useRecoilValue(isFlyingBackAtom);
const bbox = useAtomValue(bboxAtom);
const tmpBbox = useAtomValue(tmpBboxAtom);
// const isFlyingBack = useAtomValue(isFlyingBackAtom);

const layersInteractiveIds = useRecoilValue(layersInteractiveIdsAtom);
const layersInteractiveIds = useAtomValue(layersInteractiveIdsAtom);

const setBbox = useSetRecoilState(bboxAtom);
const setTmpBbox = useSetRecoilState(tmpBboxAtom);
const setBbox = useSetAtom(bboxAtom);
const setTmpBbox = useSetAtom(tmpBboxAtom);

const pathname = usePathname();

Expand Down
Loading

0 comments on commit ea6323f

Please sign in to comment.