State refactored using reducer

This commit is contained in:
David
2021-03-10 19:27:36 +01:00
parent 61f83278bc
commit 8f33cb92f2
3 changed files with 57 additions and 12 deletions

View File

@@ -1,36 +1,43 @@
import { useState, useEffect, FC } from "react"; import { useEffect, useReducer, FC, ChangeEvent } from "react";
import { GetStaticPaths, GetStaticProps, InferGetStaticPropsType } from "next"; import { GetStaticPaths, GetStaticProps, InferGetStaticPropsType } from "next";
import { useRouter } from "next/router"; import { useRouter } from "next/router";
import Error from "next/error"; import Error from "next/error";
import { googleScrape, extractSlug } from "../utils/translate"; import { googleScrape, extractSlug } from "../utils/translate";
import Languages from "../components/Languages"; import Languages from "../components/Languages";
import { languages, exceptions } from "../utils/languages.json"; import { languages, exceptions } from "../utils/languages.json";
import langReducer, { Actions, initialState } from "../utils/reducer";
const Page: FC<InferGetStaticPropsType<typeof getStaticProps>> = ({ translation, error, initial }) => { const Page: FC<InferGetStaticPropsType<typeof getStaticProps>> = ({ translation, error, initial }) => {
if (error) if (error)
return <Error statusCode={error} /> return <Error statusCode={error} />
const router = useRouter(); const [{ source, target, query }, dispatch] = useReducer(langReducer, initialState);
const [source, setSource] = useState("auto"); const handleChange = (e: ChangeEvent<HTMLInputElement | HTMLSelectElement>) => {
const [target, setTarget] = useState("en"); dispatch({
const [query, setQuery] = useState(""); type: Actions.SET_FIELD,
payload: {
key: e.target.id,
value: e.target.value
}
});
};
const router = useRouter();
const updateTranslation = () => { const updateTranslation = () => {
query && router.push(`/${source}/${target}/${query}`); query && router.push(`/${source}/${target}/${query}`);
}; };
useEffect(() => { useEffect(() => {
initial?.source && setSource(initial.source); initial && dispatch({ type: Actions.SET_ALL, payload: { state: initial }});
initial?.target && setTarget(initial.target);
initial?.query && setQuery(initial.query);
}, [initial]); }, [initial]);
useEffect(() => { useEffect(() => {
if (!query || query === initial?.query) if (!query || query === initial?.query)
return; return;
const timeout = setTimeout(updateTranslation, 1500); const timeout = setTimeout(updateTranslation, 1000);
return () => clearTimeout(timeout); return () => clearTimeout(timeout);
}, [query]); }, [query]);
@@ -46,7 +53,7 @@ const Page: FC<InferGetStaticPropsType<typeof getStaticProps>> = ({ translation,
<label htmlFor="source"> <label htmlFor="source">
Source: Source:
</label> </label>
<select id="source" value={source} onChange={e => setSource(e.target.value)}> <select id="source" value={source} onChange={handleChange}>
<Languages langs={sourceLangs} /> <Languages langs={sourceLangs} />
</select> </select>
</div> </div>
@@ -54,7 +61,7 @@ const Page: FC<InferGetStaticPropsType<typeof getStaticProps>> = ({ translation,
<label htmlFor="target"> <label htmlFor="target">
Target: Target:
</label> </label>
<select id="target" value={target} onChange={e => setTarget(e.target.value)}> <select id="target" value={target} onChange={handleChange}>
<Languages langs={targetLangs} /> <Languages langs={targetLangs} />
</select> </select>
</div> </div>
@@ -62,7 +69,7 @@ const Page: FC<InferGetStaticPropsType<typeof getStaticProps>> = ({ translation,
<label htmlFor="query"> <label htmlFor="query">
Query: Query:
</label> </label>
<input type="text" id="query" value={query} onChange={e => setQuery(e.target.value)} /> <input type="text" id="query" value={query} onChange={handleChange} />
</div> </div>
<div> <div>
{translation} {translation}

View File

@@ -121,6 +121,7 @@
}, },
"mappings": { "mappings": {
"target": { "target": {
"zh": "zh-CN",
"zh_HANT": "zh-TW" "zh_HANT": "zh-TW"
} }
} }

37
utils/reducer.ts Normal file
View File

@@ -0,0 +1,37 @@
export enum Actions {
"SET_FIELD",
"SET_ALL"
}
export const initialState = {
source: "auto",
target: "en",
query: ""
}
type Action = {
type: Actions.SET_FIELD,
payload: {
key: string,
value: string
}
} | {
type: Actions.SET_ALL,
payload: {
state: {
[key: string]: string
}
}
}
export default function reducer(state: typeof initialState, action: Action) {
switch (action.type) {
case Actions.SET_FIELD:
const { key, value } = action.payload;
return { ...state, [key]: value };
case Actions.SET_ALL:
return { ...state, ...action.payload.state };
default:
return state;
}
}