Skip to content

Commit

Permalink
#9: Add Redux to manage app state
Browse files Browse the repository at this point in the history
  • Loading branch information
williamquintas committed May 30, 2022
1 parent 41d3f38 commit 3c36049
Show file tree
Hide file tree
Showing 11 changed files with 174 additions and 61 deletions.
2 changes: 1 addition & 1 deletion .env
Original file line number Diff line number Diff line change
@@ -1 +1 @@
REACT_APP_GOOGLE_API_KEY = "string"
NEXT_PUBLIC_GOOGLE_API_KEY = "string"
40 changes: 19 additions & 21 deletions components/FilesSelectionContainer/FilesSelectionContainer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,19 +13,21 @@ import {
} from "@mui/material";
import Papa from "papaparse";
import { ChangeEvent, FunctionComponent } from "react";
import { IFile } from "../../pages/_app";
import { useAppDispatch, useAppSelector } from "../../config/hooks";
import {
add,
changeColor,
remove,
selectFiles,
} from "../../features/files/slice";
import ColorPicker, { Colors } from "../ColorPicker/ColorPicker";
import FileUploadButton from "../FileUploadButton/FileUploadButton";
import Link from "../Link/Link";

interface FilesSelectionContainerProps {
files: IFile[];
setFiles: (files: IFile[]) => void;
}
const FilesSelectionContainer: FunctionComponent = () => {
const dispatch = useAppDispatch();
const files = useAppSelector(selectFiles);

const FilesSelectionContainer: FunctionComponent<
FilesSelectionContainerProps
> = ({ files, setFiles }) => {
const getRandomColor = (): string => {
const colors = Object.keys(Colors);
const index = Math.floor(Math.random() * colors.length) + 1;
Expand All @@ -39,13 +41,13 @@ const FilesSelectionContainer: FunctionComponent<
header: true,
skipEmptyLines: true,
complete: ({ data }) => {
const filesList = [...files];
filesList.push({
filename: file.name,
color: getRandomColor(),
data,
});
setFiles(filesList);
dispatch(
add({
filename: file.name,
color: getRandomColor(),
data,
})
);
},
error: (error) => console.error(error),
});
Expand All @@ -67,9 +69,7 @@ const FilesSelectionContainer: FunctionComponent<
};

const onRemoveFile = (index: number) => {
const filesList = [...files];
filesList.splice(index, 1);
setFiles(filesList);
dispatch(remove(index));
};

const onChangeColor = (index: number, evt: SelectChangeEvent) => {
Expand All @@ -79,9 +79,7 @@ const FilesSelectionContainer: FunctionComponent<
return;
}

const filesList = [...files];
filesList[index].color = selectedColor;
setFiles(filesList);
dispatch(changeColor({ index, color: selectedColor }));
};

return (
Expand Down
6 changes: 3 additions & 3 deletions components/Map/Map.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -60,18 +60,18 @@ interface MapProps {
}

const Map: FunctionComponent<MapProps> = ({ files }) => {
const { REACT_APP_GOOGLE_API_KEY } = process.env;
const NEXT_PUBLIC_GOOGLE_API_KEY = process.env.NEXT_PUBLIC_GOOGLE_API_KEY;
const center = {
lat: Number(files[0]?.data?.[0].latitude),
lng: Number(files[0]?.data?.[0].longitude),
};

if (!REACT_APP_GOOGLE_API_KEY) {
if (!NEXT_PUBLIC_GOOGLE_API_KEY) {
throw new Error("No Google Maps API Key specified.");
}

return (
<Wrapper apiKey={REACT_APP_GOOGLE_API_KEY}>
<Wrapper apiKey={NEXT_PUBLIC_GOOGLE_API_KEY}>
<MapContainer center={center} zoom={14} files={files} />
</Wrapper>
);
Expand Down
6 changes: 6 additions & 0 deletions config/hooks.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { TypedUseSelectorHook, useDispatch, useSelector } from "react-redux";
import type { AppDispatch, AppState } from "./store";

export const useAppDispatch = () => useDispatch<AppDispatch>();

export const useAppSelector: TypedUseSelectorHook<AppState> = useSelector;
23 changes: 23 additions & 0 deletions config/store.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { Action, configureStore, ThunkAction } from "@reduxjs/toolkit";
import filesReducer from "../features/files/slice";

export function makeStore() {
return configureStore({
reducer: { files: filesReducer },
});
}

const store = makeStore();

export type AppState = ReturnType<typeof store.getState>;

export type AppDispatch = typeof store.dispatch;

export type AppThunk<ReturnType = void> = ThunkAction<
ReturnType,
AppState,
unknown,
Action<string>
>;

export default store;
43 changes: 43 additions & 0 deletions features/files/slice.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { createSlice, PayloadAction } from "@reduxjs/toolkit";
import type { AppState } from "../../config/store";
import { IFile } from "../../pages/_app";

export interface FilesState {
files: IFile[];
}

const initialState: FilesState = {
files: [],
};

export const filesSlice = createSlice({
name: "files",
initialState,
reducers: {
add: (state, action: PayloadAction<IFile>) => {
const currentFiles = [...state.files];
currentFiles.push(action.payload);
state.files = currentFiles;
},
remove: (state, action: PayloadAction<number>) => {
const currentFiles = [...state.files];
currentFiles.splice(action.payload);
state.files = currentFiles;
},
changeColor: (
state,
action: PayloadAction<{ index: number; color: string }>
) => {
const currentFiles = [...state.files];
const { index, color } = action.payload;
currentFiles[index].color = color;
state.files = currentFiles;
},
},
});

export const { add, remove, changeColor } = filesSlice.actions;

export const selectFiles = (state: AppState) => state.files.files;

export default filesSlice.reducer;
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
"@googlemaps/react-wrapper": "^1.1.33",
"@mui/icons-material": "^5.6.2",
"@mui/material": "^5.7.0",
"@reduxjs/toolkit": "^1.8.2",
"@types/google.maps": "^3.48.8",
"@types/node": "^17.0.32",
"@types/react": "^18.0.9",
Expand All @@ -18,7 +19,7 @@
"papaparse": "^5.3.2",
"react": "^18.1.0",
"react-dom": "^18.1.0",
"react-router-dom": "6",
"react-redux": "^8.0.2",
"react-scripts": "5.0.1",
"typescript": "^4.6.4"
},
Expand Down
6 changes: 5 additions & 1 deletion pages/_app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@ import { Box, CssBaseline, ThemeProvider } from "@mui/material";
import { AppProps } from "next/app";
import Head from "next/head";
import { useState } from "react";
import { Provider } from "react-redux";
import Footer from "../components/Footer/Footer";
import Header from "../components/Header/Header";
import store from "../config/store";
import theme from "../config/theme";
import "../css/ColorPicker.css";
import "../css/FilesSelectionContainer.css";
Expand Down Expand Up @@ -59,7 +61,9 @@ export default function App({
}}
>
<Header />
<Component {...pageProps} />
<Provider store={store}>
<Component {...pageProps} />
</Provider>
<Footer />
</Box>
</ThemeProvider>
Expand Down
6 changes: 2 additions & 4 deletions pages/index.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
import { FunctionComponent, useState } from "react";
import { FunctionComponent } from "react";
import FilesSelectionContainer from "../components/FilesSelectionContainer/FilesSelectionContainer";
import { IFile } from "./_app";

const FilesSelectionPage: FunctionComponent = () => {
const [files, setFiles] = useState<IFile[]>([]);
return <FilesSelectionContainer files={files} setFiles={setFiles} />;
return <FilesSelectionContainer />;
};

export default FilesSelectionPage;
10 changes: 4 additions & 6 deletions pages/map.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,12 @@ import { useRouter } from "next/router";
import { FunctionComponent, useEffect } from "react";
import CoordinatesList from "../components/CoordinatesList/CoordinatesList";
import Map from "../components/Map/Map";
import { IFile } from "./_app";
import { useAppSelector } from "../config/hooks";
import { selectFiles } from "../features/files/slice";

interface MapViewerPageProps {
files: IFile[];
}

const MapViewerPage: FunctionComponent<MapViewerPageProps> = ({ files }) => {
const MapViewerPage: FunctionComponent = () => {
const router = useRouter();
const files = useAppSelector(selectFiles);

useEffect(() => {
if (!files || files.length === 0) {
Expand Down
Loading

0 comments on commit 3c36049

Please sign in to comment.