La herramienta que menciona el profesor en el minuto 11 se puede encontrar en https://tomekdev.com/posts/throttle-vs-debounce-on-real-examples
Introducción
¿Cuándo optimizar el código?
Throttling y Debouncing
Analizando nuestra página de búsqueda
Nuestro propio hook debouncer: useDebouncer
Throttling y Debouncing con Lodash en React
Cache en memoria
Asincronía, cache y re-validación de recursos HTTP
Hashmaps vs. arrays
Memoización
Identificando re-renders problemáticos
Memoization en React
Scrolling
Patrón Windowing
Conclusiones
Próximos pasos
Comando: git checkout -b dev 2-env-vars
Aportes 7
Preguntas 0
La herramienta que menciona el profesor en el minuto 11 se puede encontrar en https://tomekdev.com/posts/throttle-vs-debounce-on-real-examples
¿Por qué optimizar?
Invocar una función menos veces.
Proteger y optimizar recursos.
Archivos base de la clase.
pages/search.tsx
import { useState, ChangeEventHandler, useEffect } from 'react'
import { serverSideTranslations } from 'next-i18next/serverSideTranslations'
import { useTranslation } from 'next-i18next'
import { GetStaticProps } from 'next'
import {
OutlinedInput,
InputLabel,
InputAdornment,
FormControl,
} from '@ui/FormField'
import { SearchIcon } from '@ui/icon/Search'
import { Typography } from '@ui/Typography'
import { Layout } from '@components/Layout'
import { PlantCollection } from '@components/PlantCollection'
import { searchPlants, QueryStatus } from '@api'
export const getStaticProps: GetStaticProps = async ({ locale }) => ({
props: await serverSideTranslations(locale!),
})
export default function Search() {
const { t } = useTranslation(['page-search'])
const [term, setTerm] = useState('')
const [status, setStatus] = useState<QueryStatus>('idle')
const [results, setResults] = useState<Plant[]>([])
const updateTerm: ChangeEventHandler<HTMLInputElement> = (event) =>
setTerm(event.currentTarget.value)
const emptyResults = status === 'success' && results.length === 0
useEffect(() => {
if (term.trim().length < 3) {
setStatus('idle')
setResults([])
return
}
setStatus('loading')
// Pagination not supported... yet
searchPlants({
term,
limit: 10,
}).then((data) => {
setResults(data)
setStatus('success')
})
}, [term])
return (
<Layout>
<main className="pt-16 text-center">
<div className="max-w-5xl mx-auto mb-6">
<FormControl fullWidth className="" variant="outlined">
<InputLabel htmlFor="search-term-field">{t('term')}</InputLabel>
<OutlinedInput
id="search-term-field"
value={term}
onChange={updateTerm}
startAdornment={
<InputAdornment position="start">
<SearchIcon />
</InputAdornment>
}
labelWidth={100}
/>
</FormControl>
</div>
<div>
{emptyResults ? (
<Typography variant="body1">{t('notFound', { term })}</Typography>
) : null}
</div>
<div>
{!emptyResults ? (
<PlantCollection plants={results} variant="square" />
) : null}
</div>
</main>
</Layout>
)
}
components/Header/Header.tsx
import { PropsWithChildren } from 'react'
import Link, { LinkProps } from 'next/link'
import { useTranslation } from 'next-i18next'
import { NavBar } from '@ui/NavBar'
import { Button } from '@ui/Button'
import { PreviewModeBanner } from './PreviewModeBanner'
import { TopArea } from './TopArea'
export function Header() {
const { t } = useTranslation(['common'])
return (
<>
<PreviewModeBanner />
<div className='px-8 py-3'>
<TopArea />
</div>
<div className="mx-auto" style={{ maxWidth: '98%' }}>
<NavBar title="🌿 Plantpedia">
<div>
<NavLink href="/top-stories">{t('topStories')}</NavLink>
</div>
<NavLink href="/search">{t('search')}</NavLink>
</NavBar>
</div>
</>
)
}
function NavLink({ children, ...linkProps }: PropsWithChildren<LinkProps>) {
return (
<Link {...linkProps} passHref>
<Button color="inherit" variant="text" component="a">
{children}
</Button>
</Link>
)
}
Los archivos y el comando mostrados en los recursos no corresponden con lo que el profesor muestra…
Se puede cambiar
labelWidth={100}
Por
label={t('term')}
¿Quieres ver más aportes, preguntas y respuestas de la comunidad?
o inicia sesión.