State refactored using reducer
This commit is contained in:
@@ -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}
|
||||||
|
|||||||
@@ -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
37
utils/reducer.ts
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user