-
-
Notifications
You must be signed in to change notification settings - Fork 130
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Refactored custom hooks and contexts
- Loading branch information
1 parent
fa19b37
commit 2ac0718
Showing
15 changed files
with
255 additions
and
197 deletions.
There are no files selected for viewing
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,10 +1,10 @@ | ||
[ | ||
{ | ||
"language": "Sass", | ||
"lang": "SCSS", | ||
"icon": "/icons/sass.svg" | ||
}, | ||
{ | ||
"language": "CSS", | ||
"lang": "CSS", | ||
"icon": "/icons/css.svg" | ||
} | ||
] |
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
import { useAppContext } from "../contexts/AppContext"; | ||
import { useCategories } from "../hooks/useCategories"; | ||
|
||
const CategoryList = () => { | ||
const { category, setCategory } = useAppContext(); | ||
const { fetchedCategories } = useCategories(); | ||
|
||
return ( | ||
<ul role="list" className="categories"> | ||
{fetchedCategories.map((name) => ( | ||
<li className="category"> | ||
<button | ||
className={`category__btn ${ | ||
name === category ? "category__btn--active" : "" | ||
}`} | ||
onClick={() => setCategory(name)} | ||
> | ||
{name} | ||
</button> | ||
</li> | ||
))} | ||
</ul> | ||
); | ||
}; | ||
|
||
export default CategoryList; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
import { useAppContext } from "../contexts/AppContext"; | ||
import { useLanguages } from "../hooks/useLanguages"; | ||
|
||
const LanguageSelector = () => { | ||
const { fetchedLanguages, loading, error } = useLanguages(); | ||
const { setLanguage } = useAppContext(); | ||
|
||
const handleLanguageChange = ( | ||
event: React.ChangeEvent<HTMLSelectElement> | ||
) => { | ||
const selectedLanguage = fetchedLanguages.find( | ||
(language) => language.lang === event.target.value | ||
); | ||
if (selectedLanguage) { | ||
setLanguage(selectedLanguage); | ||
} | ||
}; | ||
|
||
if (loading) { | ||
return <p>Loading languages...</p>; | ||
} | ||
|
||
if (error) { | ||
return <p>Error fetching languages: {error}</p>; | ||
} | ||
|
||
return ( | ||
<> | ||
<select | ||
id="languages" | ||
className="language-selector" | ||
onChange={handleLanguageChange} | ||
defaultValue="CSS" | ||
> | ||
{fetchedLanguages.map((language, idx) => ( | ||
<option key={idx} value={language.lang}> | ||
{language.lang} | ||
</option> | ||
))} | ||
</select> | ||
</> | ||
); | ||
}; | ||
|
||
export default LanguageSelector; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
import { useAppContext } from "../contexts/AppContext"; | ||
import { useSnippets } from "../hooks/useSnippets"; | ||
import Button from "./Button"; | ||
import { CopyIcon, ExpandIcon } from "./Icons"; | ||
|
||
const SnippetList = () => { | ||
const { language } = useAppContext(); | ||
const { fetchedSnippets } = useSnippets(); | ||
|
||
if (!fetchedSnippets) return <p>Empty List</p>; | ||
|
||
return ( | ||
<ul role="list" className="snippets"> | ||
{fetchedSnippets.map((snippet) => ( | ||
<li className="snippet"> | ||
<div className="snippet__preview"> | ||
<img src={language.icon} alt={language.lang} /> | ||
<Button isIcon={true} className="snippet__copy"> | ||
<CopyIcon /> | ||
</Button> | ||
</div> | ||
|
||
<div className="snippet__content"> | ||
<h3 className="snippet__title">{snippet.title}</h3> | ||
<Button isIcon={true}> | ||
<ExpandIcon /> | ||
</Button> | ||
</div> | ||
</li> | ||
))} | ||
</ul> | ||
); | ||
}; | ||
|
||
export default SnippetList; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
import { createContext, useContext, useState } from "react"; | ||
import { AppState, LanguageType, SnippetType } from "../types"; | ||
|
||
// tokens | ||
const defaultLanguage: LanguageType = { | ||
lang: "CSS", | ||
icon: "/icons/css.svg", | ||
}; | ||
|
||
const defaultCategory: string = "DOM Manipulation"; | ||
|
||
const defaultState: AppState = { | ||
language: defaultLanguage, | ||
setLanguage: () => {}, | ||
category: defaultCategory, | ||
setCategory: () => {}, | ||
setSnippet: () => {}, | ||
}; | ||
|
||
const AppContext = createContext<AppState>(defaultState); | ||
|
||
export const useAppContext = () => useContext(AppContext); | ||
|
||
export const AppProvider: React.FC<{ children: React.ReactNode }> = ({ | ||
children, | ||
}) => { | ||
const [language, setLanguage] = useState<LanguageType>(defaultLanguage); | ||
const [category, setCategory] = useState<string>(defaultCategory); | ||
const [snippet, setSnippet] = useState<SnippetType>(); | ||
|
||
return ( | ||
<AppContext.Provider | ||
value={{ | ||
language, | ||
setLanguage, | ||
category, | ||
setCategory, | ||
snippet, | ||
setSnippet, | ||
}} | ||
> | ||
{children} | ||
</AppContext.Provider> | ||
); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,29 +1,20 @@ | ||
import { useEffect, useState } from "react"; | ||
import { LanguageData } from "../types"; | ||
import { useFetch } from "./useFetch"; | ||
import { useAppContext } from "../contexts/AppContext"; | ||
import { SnippetType } from "../types"; | ||
import slugify from "../utils/slugify"; | ||
|
||
export const useCategories = (language: string) => { | ||
const [fetchedCategories, setFetchedCategories] = useState<string[]>([]); | ||
|
||
useEffect(() => { | ||
const fetchCategories = async () => { | ||
try { | ||
const res = await fetch(`/data/${language}.json`); | ||
if (!res.ok) { | ||
throw new Error("Failed to fetch languages in CategoryList.tsx"); | ||
} | ||
const data: LanguageData = await res.json(); | ||
const filteredCategoryNames = data.map( | ||
(category) => category.categoryName | ||
); | ||
type CategoryData = { | ||
categoryName: string; | ||
snippets: SnippetType[]; | ||
}; | ||
|
||
setFetchedCategories(filteredCategoryNames); | ||
} catch (error) { | ||
console.error("Error occured with CategoryList.tsx", error); | ||
} | ||
}; | ||
export const useCategories = () => { | ||
const { language } = useAppContext(); | ||
const { data, loading, error } = useFetch<CategoryData[]>( | ||
`/data/${slugify(language.lang)}.json` | ||
); | ||
|
||
fetchCategories(); | ||
}, [language]); | ||
const fetchedCategories = data ? data.map((item) => item.categoryName) : []; | ||
|
||
return { fetchedCategories }; | ||
return { fetchedCategories, loading, error }; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
import { useEffect, useState } from "react"; | ||
|
||
export const useFetch = <T>(url: string) => { | ||
const [data, setData] = useState<T | null>(null); | ||
const [error, setError] = useState<string | null>(null); | ||
const [loading, setLoading] = useState<boolean>(true); | ||
|
||
useEffect(() => { | ||
const fetchData = async () => { | ||
try { | ||
const res = await fetch(url); | ||
if (!res.ok) { | ||
throw new Error(`Failed to fetch data from ${url}`); | ||
} | ||
const result: T = await res.json(); | ||
setData(result); | ||
} catch (err) { | ||
setError((err as Error).message); | ||
} finally { | ||
setLoading(false); | ||
} | ||
}; | ||
|
||
fetchData(); | ||
}, [url]); | ||
|
||
return { data, loading, error }; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,33 +1,8 @@ | ||
import { useEffect, useState } from "react"; | ||
|
||
type LanguageType = { | ||
language: string; | ||
icon: string; | ||
}; | ||
import { LanguageType } from "../types"; | ||
import { useFetch } from "./useFetch"; | ||
|
||
export const useLanguages = () => { | ||
const [fetchedLanguages, setFetchedLanguages] = useState<LanguageType[]>([]); | ||
const [error, setError] = useState<string | null>(null); | ||
const [loading, setLoading] = useState<boolean>(true); | ||
|
||
useEffect(() => { | ||
const fetchLanguages = async () => { | ||
try { | ||
const res = await fetch(`/data/index.json`); | ||
if (!res.ok) { | ||
throw new Error("Failed to fetch languages"); | ||
} | ||
const data = await res.json(); | ||
setFetchedLanguages(data); | ||
} catch (err) { | ||
setError((err as Error).message); | ||
} finally { | ||
setLoading(false); | ||
} | ||
}; | ||
|
||
fetchLanguages(); | ||
}, []); | ||
const { data, loading, error } = useFetch<LanguageType[]>("/data/index.json"); | ||
|
||
return { fetchedLanguages, loading, error }; | ||
return { fetchedLanguages: data || [], loading, error }; | ||
}; |
Oops, something went wrong.