Executando verificação de segurança...
1

[DÚVIDA] Fluxo correto de páginas com pesquisa dinâmica com Nextjs

Olá pessoal, espero que esteja tudo bem com todos.

Há alguns anos venho estudando e trabalhando com a biblioteca React e recentemente decidi dedicar meus estudos ao framework Nextjs.

Já consegui avançar muitos nos conceitos do Next e entender como ele funciona, porém ainda existem alguns pontos que estão meio nublados e nao consigo entender qual seria o fluxo correto.

Nesse Post eu gostaria de abordar o seguinte assunto "Como funcionam as pesquisas dinâmicas com NextJs", tenho tentado encontrar conteudos na internet que expliquem como funciona esse fluxo de uma forma profissional, como é usado pelos desenvolvedores no dia-a-dia, mas não consegui encontrar nada a respeito.

Um exemplo da minha dúvida é a seguinte, vamos supor que temos uma e-comerce e nós temos um input de pesquisa na home, de acordo com o que a gente pesquisa nesse input nós somos redirecionados para uma outra página que trás os resultados da nossa busca, nesta página para onde fomos redirecionados nós podemos pesquisar novamente por outro produto, porém dessa vez nós não somos redirecionados para outra rota, oque muda é apenas a listagem dos produtos, que agora é coerente com a busca que fizemos.

Levando em conta as funcionalidades de SSR do next eu gostaria de saber qual é a maneira mais profissional para se implementar isso no dia-a-dia? Como isso é feito?

Utilizando apenas a lib React podemos fazer isso facilmente utilizando um estado, quando ao clicar no botão de pesquisa é feito um request e alteramos esse estado, mas com Next onde podemos aproveitar mais o SSR e trazer o conteudo pré renderizado do servidor, como fariamos isso?

Essa é uma das minhas maiores dúvidas, caso alguém possa me auxiliar explicando como é feito esse fluxo da maneira correta ou até mesmo indicar algum conteudo que explique sobre, ficaria grato.

Agradeço a atenção de todos desde já.

Carregando publicação patrocinada...
2

Olá!

Entendo sua dúvida e agradeço por compartilhar o contexto completo. Vamos abordar a questão de pesquisas dinâmicas com Next.js e como isso pode ser implementado de forma eficaz.

Primeiramente, é importante mencionar que, não existe uma única "maneira correta" de implementar tais funcionalidades. A abordagem a ser adotada depende muito das necessidades específicas do projeto, da infraestrutura disponível e das preferências da equipe de desenvolvimento.

  1. Pesquisa Dinâmica com Renderização no Servidor:

    Quando um usuário realiza uma pesquisa, você pode fazer uma consulta ao banco de dados no servidor, renderizar a página com os resultados e enviá-la ao cliente.

    Como implementar: Quando o usuário clica no botão de pesquisa, ele é redirecionado para uma nova rota (por exemplo, /search?query=produto). No lado do servidor, o Next.js captura o parâmetro de consulta, faz a busca no banco de dados e renderiza a página com os resultados.

import database from '/db-path';
export default function Search() {
  ...
  return (
    <div>
      <input value={query} onChange={e => setQuery(e.target.value)} />
      <button onClick={() => {}}>Search</button>
      {results.map(result => (
        <div key={result.id}>{result.name}</div>
      ))}
    </div>
  );
}

export async function getServerSideProps(context) {
  const results = await database.search(context.query); 
  return { props: { results } };
}
  1. Pesquisa Dinâmica com Renderização no Cliente:

    Para pesquisas subsequentes na página de resultados, você pode optar por não redirecionar o usuário para uma nova rota. Em vez disso, a pesquisa é realizada no lado do cliente, e os resultados são atualizados dinamicamente.

    Como implementar: Utilize estados para armazenar os resultados da pesquisa. Quando o usuário faz uma nova pesquisa, faça uma chamada API para buscar os novos resultados e atualize o estado. Com isso, a lista de produtos será re-renderizada automaticamente.

export default function Search() {
  ...
  async function handleSearch() {
    const res = await fetch(`/api/search?query=${query}`);
    const data = await res.json();
    setResults(data.results);
  }

  return (
    <div>
      <input value={query} onChange={e => setQuery(e.target.value)} />
      <button onClick={handleSearch}>Search</button>
      {results.map(result => (
        <div key={result.id}>{result.name}</div>
      ))}
    </div>
  );
}
  1. Filtragem Dinâmica e Renderização no Servidor:

    Armazene os dados a serem pesquisados em memôria em sua aplicação. A filtragem é realizada pela aplicação no servidor antes de enviar à página redenrizada ao cliente.

    Como implementar: Inicialmente, carregue os dados a serem pesquisados em cache no servidor, seja usando uma solução como Redis ou simplesmente armazenando em memória. Quando um usuário realiza uma pesquisa no cliente, a query de busca é enviada ao servidor que filtra os dados em memória com base na consulta do usuário e envia a página renderizada com esses resultados.

import cache from '/chache-path';
export default function Search() {
  return (
    <div>
      <input value={query} onChange={e => setQuery(e.target.value)} />
      <button onClick={() => {}}>Search</button>
      {results.map(result => (
        <div key={result.id}>{result.name}</div>
      ))}
    </div>
  );
}

export async function getServerSideProps(context) {
  const results = cache.filter(item => item.name.includes(query)); 
  return { props: { results } };
}
  1. Filtragem Dinâmica e Renderização no Cliente:

    Com os resultados em cache enviados para o cliente, a filtragem é realizada no lado do cliente usando JavaScript. Isso permite uma resposta rápida e dinâmica às ações do usuário.

    Como implementar: O clique faz uma requisão com os dados a serem buscados, armazene-os em um estado no React. Use um input de pesquisa para capturar a consulta do usuário. Ao digitar, use JavaScript para filtrar os resultados salvos no cliente com base na consulta e atualize a UI dinamicamente com os resultados filtrados.

export default function Search({ cachedData }) {
  ...
  function handleSearch() {
    const filteredResults = cachedData.filter(item => item.name.includes(query));
    setResults(filteredResults);
  }

  return (
    <div>
      <input value={query} onChange={e => setQuery(e.target.value)} />
      <button onClick={handleSearch}>Search</button>
      {results.map(result => (
        <div key={result.id}>{result.name}</div>
      ))}
    </div>
  );
}

export async function getStaticProps() {
  const cachedData = await fetchData();
  return { props: { cachedData } };
}
  • Outras Considerações Importantes indepedente da solução que optar:
  1. Paginação e Lazy Loading: Em vez de carregar todos os resultados de uma vez, você pode implementar a paginação ou o lazy loading. Isso é especialmente útil quando há muitos resultados a serem exibidos.

  2. Debounce no input do usuário: Ao implementar a pesquisa dinâmica no cliente, considere usar uma função debounce. Isso significa que a chamada API ou a filtragem dos resultados será realizada após o usuário parar de digitar por um determinado período de tempo.

  3. Feedback Visual para o Usuário: Ao realizar pesquisas ou filtragens, é importante fornecer feedback visual para o usuário, como spinners ou mensagens de carregamento.
    Benefício: Melhora a experiência do usuário ao informá-lo sobre o que está acontecendo.

  • Considerações para escolher a solução mais adequada:
  1. Performance do Banco de Dados: Se o banco de dados for rápido e otimizado, fazer consultas frequentes pode não ser um problema. No entanto, se houver muitos dados ou se a consulta for complexa, isso pode afetar a performance. Em arquitetura mais robustas e complexas, é possivel ter um banco de dados ou ao menos conexões, dedicadas e otimizadas exclusivamente para fazer as buscas.

  2. Quantidade de Dados: Enviar "todos os dados" para o frontend e filtrar no cliente, sem a necessidade de requisões subsequentes ao servidos, pode ser viável e mais flúido se houver uma quantidade de dados relativamente pequena.

  3. Experiência do Usuário: Redirecionar o usuário para uma nova página pode não ser a melhor experiência em todos os casos. Às vezes, atualizar dinamicamente os resultados na mesma página é mais fluido.

A chave é entender suas necessidades e requisitos. Como mencionado, cada solução tem suas vantagens e desvantagens. O importante é avaliar o trade-off entre performance, experiência do usuário e complexidade de implementação e combiná-las de acordo com suas necessidades.

Uma solução idealizada para máxima performance e responsividade envolveria múltiplas camadas de cache, filtragem de dados dinâmicos no cliente e um banco de dados dedicado exclusivamente para estas consultas. Esta abordagem proporcionaria atualizações virtualmente instantâneas na interface do usuário em qualquer cenário.

No entanto, na maioria das aplicações tal complexidade não é justificada. É fundamental encontrar um equilíbrio que atenda às necessidades do projeto sem comprometer a experiência do usuário ou exceder os recursos disponíveis. A solução "mais profissional" é aquela que é adaptada e eficaz para o seu caso específico.

1

Muito obrigado por toda a explicação, consegui entender muito bem e vou tentar colocar em prática todos esses conceitos para aperfeiçoa-los.

Mas ainda tem um ponto que a dúvida persiste...

Vamos imaginar que nós temos que simular um fastrefresh na página, por exemplo: Estamos na pagina de pesquisa de produtos de um e-commerce e digitamos por um produto na barra de busca, nisso a listagem de produtos é atualizada conforme oque foi pesquisado na barra de pesquisa, porém para fazer a atualização da listagem não houve um recarregamento da página, aconteceu como se tivessemos trocado um estado da aplicação utilizando React, nesse caso em especifico, como poderiamos fazer isso utilizando SSR com Next?

Se pegarmos um site por exemplo a Kabum que é feita com Nextjs, se buscarmos por um mouse e depois aplicarmos alguns filtros na pesquisa conseguimos ver que a url muda adicionando alguns parâmetros de filtro e em seguida a listagem dos produtos muda mas não recarrega a página, o comportamento que eu gostaria de simular e entender como funciona seria esse.

Na verdade eu gostaria de entender se em comportamentos como esse nós teriamos que abrir mão do SSR e fazer tudo pelo Client ou se tem alguma forma de simular isso com o SSR?

Em um processo mais simples onde nós poderiamos ter o reload da página eu acredito que poderiamos utilizar o SSR da seguinte forma, sempre que a pesquisa for feita basta chamar a rota de listagem de produtos com os parametros da pesquisa, utilizando a própria Tag ou até mesmo a tag do próprio Next, com isso nós teriamos a página recarregada com o resultado da query que mandamos no parâmetro. Porém, simular o mesmo comportamento que uma simples mudança de estados utilizando o SSR ainda é algo que não consigo entender como fazer.

1

Vamos lá! A emulação desse comportamento no Next.js é, na verdade, bastante simples: basta realizar a renderização no cliente utilizando o React.

É importante compreender que há duas abordagens principais de renderização: no lado do cliente (CSR) e no lado do servidor (SSR). Cada uma possui suas vantagens e desvantagens, e podem ser aplicadas de maneira aditiva ou subtrativa. O ideal é combinar essas soluções conforme a necessidade.

Uma das principais vantagens de frameworks como o Next.js é a flexibilidade. Ele oferece suporte nativo tanto para CSR quanto para SSR. Isso permite que os desenvolvedores optem pela abordagem mais adequada para cada cenário, e até mesmo integrem ambas em uma única página.

Esse conceito é conhecido como "Client Hydration". Trata-se do processo pelo qual uma página, inicialmente renderizada no servidor (SSR), é "hidratada" no cliente, transformando-se em uma Single Page Application (SPA). Em resumo, o conteúdo é primeiramente gerado no servidor e enviado ao navegador. Uma vez no navegador, o React "hidrata" essa página, tornando-a dinâmica e interativa, como qualquer outra página desenvolvida exclusivamente com React.