Merge pull request #97 from hongphinguyen/type-correction-and-context-memo-fix

Adding FC to all components and fixing the lack of memoization in The…
This commit is contained in:
Jean-Philippe Sirois
2019-09-17 17:09:03 -04:00
committed by GitHub
23 changed files with 105 additions and 79 deletions
Vendored
+4
View File
@@ -0,0 +1,4 @@
declare module "*.svg" {
const content: any;
export default content;
}
+1
View File
@@ -28,6 +28,7 @@
"test": "echo \"Write tests! -> https://gatsby.dev/unit-testing\""
},
"dependencies": {
"@reach/router": "^1.2.1",
"gatsby": "^2.13.51",
"gatsby-image": "^2.2.8",
"gatsby-plugin-layout": "^1.1.2",
+2 -6
View File
@@ -1,8 +1,4 @@
import React, { useMemo, useState } from "react"
interface ISidebarProviderProps {
children: React.ReactNode
}
import React, { FC, useMemo, useState } from "react"
export interface ISidebarContextInterface {
current: number
@@ -13,7 +9,7 @@ export const SidebarContext = React.createContext<ISidebarContextInterface | nul
null
)
export function SidebarProvider({ children }: ISidebarProviderProps) {
export const SidebarProvider: FC = ({ children }) => {
const [current, setCurrent] = useState(0)
const memoizedContextValue = useMemo(
+25 -15
View File
@@ -1,32 +1,42 @@
import React, { createContext } from "react"
import React, { createContext, FC, useMemo } from "react"
import { ThemeProvider as BaseThemeProvider } from "styled-components"
import { darkTheme, lightTheme } from "./design/themes"
import { useLocalStorage } from "./hooks/useLocalStorage"
interface IThemeProviderProps {
// TODO: type this properly, BaseThemeProvider doesn't like React.ReactNode
children: any
}
export interface IThemeContext {
theme: "dark" | "light"
setTheme: () => void
toggleTheme: () => void
}
export const ThemeContext = createContext<IThemeContext | null>(null)
const ThemeProvider = ({ children }: IThemeProviderProps) => {
const [theme, setTheme] = useLocalStorage("theme", "light")
const themeObject = theme === "dark" ? darkTheme : lightTheme
const toggleTheme = () => {
setTheme(theme === "light" ? "dark" : "light")
interface IScopedDownChildren {
children: JSX.Element
}
export const ThemeContext = createContext<IThemeContext | null>(null)
const ThemeProvider: FC<IScopedDownChildren> = ({ children }) => {
const [theme, setTheme] = useLocalStorage("theme", "light")
const themeObject = useMemo(
() => (theme === "dark" ? darkTheme : lightTheme),
[theme]
)
const contextValue = useMemo(
() => ({
theme,
setTheme,
toggleTheme: () => {
setTheme(theme === "light" ? "dark" : "light")
},
}),
[theme, setTheme]
)
return (
<ThemeContext.Provider value={{ theme, setTheme, toggleTheme }}>
<ThemeContext.Provider value={contextValue}>
<BaseThemeProvider theme={themeObject}>{children}</BaseThemeProvider>
</ThemeContext.Provider>
)
+3 -3
View File
@@ -1,9 +1,9 @@
import React, { PropsWithChildren } from "react"
import React, { FC } from "react"
import * as SC from "./styles"
export function Container({
export const Container: FC = ({
children,
...restProps
}: PropsWithChildren<{}>): JSX.Element {
}) => {
return <SC.ContainerWrapper {...restProps}>{children}</SC.ContainerWrapper>
}
+2 -2
View File
@@ -1,7 +1,7 @@
import React, { PropsWithChildren } from "react"
import React, { FC } from "react"
import * as SC from "./styles"
export function DiscordButton({ children }: PropsWithChildren<{}>) {
export const DiscordButton: FC = ({ children }) => {
return (
<SC.DiscordButtonWrapper>
<SC.StyledDiscordLogo /> {children}
+2 -2
View File
@@ -1,8 +1,8 @@
import React from "react"
import React, { FC } from "react"
import { Container } from "../Container"
import * as SC from "./styles"
export function Footer() {
export const Footer: FC = () => {
return (
<SC.FooterWrapper>
<Container>
+7 -3
View File
@@ -1,5 +1,5 @@
import { Link } from "gatsby"
import React, { PropsWithChildren, useLayoutEffect, useState } from "react"
import React, { FC, useLayoutEffect, useState } from "react"
import { DiscordButton } from "../DiscordButton"
import { WavesBottom, WavesTop } from "../Waves"
import * as SC from "./styles"
@@ -8,7 +8,11 @@ interface IHeaderProps {
isHome: boolean
}
function MenuItem({ children, to }: PropsWithChildren<{ to: string }>) {
interface IMenuItemProps {
to: string
}
const MenuItem: FC<IMenuItemProps> = ({ children, to }) => {
return (
<SC.MenuItem
to={to}
@@ -21,7 +25,7 @@ function MenuItem({ children, to }: PropsWithChildren<{ to: string }>) {
)
}
export function Header({ isHome }: IHeaderProps) {
export const Header: FC<IHeaderProps> = ({ isHome }) => {
// Hack to force Particle.js to rerender
const [noop, setNoop] = useState(0)
useLayoutEffect(() => {
+5 -4
View File
@@ -5,7 +5,8 @@
* See: https://www.gatsbyjs.org/docs/use-static-query/
*/
import React, { Fragment, PropsWithChildren } from "react"
import { RouteComponentProps } from '@reach/router'
import React, { FC, Fragment } from "react"
import { GlobalStyles } from "../../globalStyles"
import { ThemeProvider } from "../../ThemeProvider"
@@ -15,11 +16,11 @@ import { Header } from "../Header"
import { WavesBottom } from "../Waves"
import * as SC from "./styles"
export function Layout({
export const Layout: FC<RouteComponentProps> = ({
children,
location,
}: PropsWithChildren<{ location: Location }>) {
const isHome = location.pathname === "/"
}) => {
const isHome = location ? location.pathname === "/" : false
return (
<ThemeProvider>
+4 -4
View File
@@ -3,7 +3,7 @@ import "prismjs/components/prism-markup-templating"
import "prismjs/components/prism-php"
import "prismjs/components/prism-python"
import "prismjs/plugins/line-numbers/prism-line-numbers.css"
import React from "react"
import React, { FC, useEffect } from "react"
import * as SC from "./styles"
interface IMarkdownProps {
@@ -14,11 +14,11 @@ interface IMarkdownProps {
This component is used as a wrapper around Markdown generated content,
mainly to provide styles to the html generated.
*/
export function Markdown({
export const Markdown: FC<IMarkdownProps> = ({
content,
...restProps
}: IMarkdownProps): JSX.Element {
React.useEffect(() => {
}) => {
useEffect(() => {
Prism.highlightAll()
}, [])
return (
+2 -2
View File
@@ -1,11 +1,11 @@
import React from "react"
import React, { FC } from "react"
import * as SC from "./styles"
interface IMobileHeaderProps {
openMenu: () => void
}
export function MobileHeader({ openMenu }: IMobileHeaderProps) {
export const MobileHeader: FC<IMobileHeaderProps> = ({ openMenu }) => {
return (
<SC.MobileHeaderWrapper>
<SC.LogoWrapper>
+6 -2
View File
@@ -1,15 +1,19 @@
import React from "react"
import React, { FC } from "react"
import ChevronUp from "../../icons/chevron-up.svg"
import { IFileOrFolder } from "../../types"
import { humanize, traversePaths } from "../../utils"
import * as SC from "./styles"
interface ILinkProps {
item: IFileOrFolder
}
interface IResourceBreadcrumbProps {
relativePath: any
}
function Link({ item }: { item: IFileOrFolder }) {
const Link: FC<ILinkProps> = ({ item }) => {
return <SC.StyledLink to={item.path}>{humanize(item.title)}</SC.StyledLink>
}
+11 -11
View File
@@ -1,4 +1,4 @@
import React, { Fragment } from "react"
import React, { FC, Fragment } from "react"
import ChevronUp from "../../icons/chevron-up.svg"
import { ResourceBreadcrumb } from "../ResourceBreadcrumb"
@@ -6,13 +6,13 @@ import { StackedAvatars } from "../StackedAvatars"
import * as SC from "./styles"
interface IResourceHeaderProps {
relativePath: any
title: any
authors: any
createdAt: any
timeToRead: any
recommendedReading: any
externalResources: any
relativePath: string
title: string
authors: string[]
createdAt: string
timeToRead: number
recommendedReading: string[]
externalResources: string[]
}
function ExtraLink({
@@ -43,7 +43,7 @@ function ExtraLink({
)
}
export function ResourceHeader({
export const ResourceHeader: FC<IResourceHeaderProps> = ({
relativePath,
title,
authors,
@@ -51,7 +51,7 @@ export function ResourceHeader({
timeToRead,
recommendedReading,
externalResources,
}: IResourceHeaderProps) {
}) => {
const date = new Date(createdAt)
const month = date.toLocaleString("default", { month: "long" })
const day = date.getDate()
@@ -67,7 +67,7 @@ export function ResourceHeader({
<SC.Top>
<SC.Meta>
<StackedAvatars authors={authors} /> {authors.length} contributor
{authors.lenght > 1 && "s"}
{authors.length > 1 && "s"}
</SC.Meta>
<SC.Meta>{dateToHuman}</SC.Meta>
<SC.Meta>
+2 -2
View File
@@ -5,7 +5,7 @@
* See: https://www.gatsbyjs.org/docs/use-static-query/
*/
import React, { PropsWithChildren, useState } from "react"
import React, { FC, useState } from "react"
import { GlobalStyles } from "../../globalStyles"
import { SidebarProvider } from "../../SidebarProvider"
@@ -14,7 +14,7 @@ import { MobileHeader } from "../MobileHeader"
import { ResourcesSidebar } from "../ResourcesSidebar"
import * as SC from "./styles"
export function ResourcesLayout({ children }: PropsWithChildren<{}>) {
export const ResourcesLayout: FC = ({ children }) => {
const [activeMobileMenu, setActiveMobileMenu] = useState(false)
function openMenu() {
+7 -5
View File
@@ -1,12 +1,14 @@
import React, { PropsWithChildren } from "react"
import React, { FC } from "react"
import * as SC from "./styles"
export function ResourcesLink({
interface IResourcesLinkProps {
to: string
}
export const ResourcesLink: FC<IResourcesLinkProps> = ({
children,
to,
}: PropsWithChildren<{
to: string
}>) {
}) => {
if (!to.match(/^(https?:\/\/)/)) {
return (
<SC.ResourcesLinkInternal to={to}>{children}</SC.ResourcesLinkInternal>
+2 -2
View File
@@ -1,5 +1,5 @@
import { graphql, useStaticQuery } from "gatsby"
import React, { memo } from "react"
import React, { FC, HTMLAttributes, memo } from "react"
import "react-perfect-scrollbar/dist/css/styles.css"
import { IAllResourcesQuery, IFileOrFolder, IFolder } from "../../types"
import { humanize } from "../../utils"
@@ -51,7 +51,7 @@ const Language = memo(({ item }: { item: IFolder; index: number }) => {
)
})
export function ResourcesList(props: React.HTMLAttributes<HTMLDivElement>) {
export const ResourcesList: FC<HTMLAttributes<HTMLDivElement>> = (props) => {
const resources = useStaticQuery<IAllResourcesQuery>(ALL_RESOURCES)
const tree = useBuildTree(resources)
+7 -3
View File
@@ -1,5 +1,5 @@
import { graphql, Link, useStaticQuery } from "gatsby"
import React, { memo, PropsWithChildren, useState } from "react"
import React, { FC, HTMLAttributes, memo, useState } from "react"
import Scrollbar from "react-perfect-scrollbar"
import "react-perfect-scrollbar/dist/css/styles.css"
import TriangleDown from "../../icons/triangle-down.svg"
@@ -83,7 +83,11 @@ const FirstLevelFolder = memo(
}
)
function MenuItem({ children, to }: PropsWithChildren<{ to: string }>) {
interface IMenuItemProps {
to: string
}
const MenuItem: FC<IMenuItemProps> = ({ children, to }) => {
return (
<SC.MenuItem to={to} activeClassName="active">
{children}
@@ -91,7 +95,7 @@ function MenuItem({ children, to }: PropsWithChildren<{ to: string }>) {
)
}
export function ResourcesSidebar(props: React.HTMLAttributes<HTMLDivElement>) {
export const ResourcesSidebar: FC<HTMLAttributes<HTMLDivElement>> = (props) => {
const resources = useStaticQuery<IAllResourcesQuery>(ALL_RESOURCES)
const tree = useBuildTree(resources)
@@ -1,14 +1,14 @@
import React, { PropsWithChildren } from "react"
import React, { FC } from "react"
import * as SC from "./styles"
export interface IResourcesSidebarSectionProps {
readonly title: string
}
export function ResourcesSidebarSection({
export const ResourcesSidebarSection: FC<IResourcesSidebarSectionProps> = ({
title,
children,
}: PropsWithChildren<IResourcesSidebarSectionProps>) {
}) => {
return (
<div>
<SC.SidebarTitle>{title}</SC.SidebarTitle>
+3 -3
View File
@@ -1,5 +1,5 @@
import { graphql, useStaticQuery } from "gatsby"
import React from "react"
import React, { FC } from "react"
import Helmet from "react-helmet"
interface ISEOProps {
@@ -10,13 +10,13 @@ interface ISEOProps {
readonly title: string
}
export function SEO({
export const SEO: FC<ISEOProps> = ({
description,
lang = "en",
meta = [],
keywords = [],
title,
}: ISEOProps) {
}) => {
const { site } = useStaticQuery(
graphql`
query {
+3 -3
View File
@@ -1,12 +1,12 @@
import React from "react"
import React, { FC } from "react"
import * as SC from "./styles"
interface IStackedAvatarsProps {
authors: any
authors: any[]
}
export function StackedAvatars({ authors }: IStackedAvatarsProps) {
export const StackedAvatars: FC<IStackedAvatarsProps> = ({ authors }) => {
return (
<SC.StackedAvatarsWrapper count={authors.length}>
{authors.map((author, index) => (
+2 -2
View File
@@ -1,8 +1,8 @@
import React from "react"
import React, { FC } from "react"
import useTheme from "../../hooks/useTheme"
import * as SC from "./styles"
export function ThemeToggler() {
export const ThemeToggler: FC = () => {
const { theme, toggleTheme } = useTheme()
return (
+3 -3
View File
@@ -1,10 +1,10 @@
import React from "react"
import React, { FC } from "react"
import * as SC from "./styles"
export function WavesTop() {
export const WavesTop: FC = () => {
return <SC.StyledWavesTop />
}
export function WavesBottom() {
export const WavesBottom: FC = () => {
return <SC.StyledWavesBottom />
}
+2 -2
View File
@@ -1,11 +1,11 @@
import { graphql } from "gatsby"
import React, { Fragment } from "react"
import React, { FC, Fragment } from "react"
import { Markdown } from "../components/Markdown"
import { ResourceHeader } from "../components/ResourceHeader"
import { SEO } from "../components/SEO"
// @todo maybe find alternative type for data
function LanguagePost({ data }: any) {
const LanguagePost: FC<any> = ({ data }) => {
const { relativePath } = data.file
const { html, fields, frontmatter, timeToRead } = data.file.post