Mutação assíncrona de dados e manipulação é uma tarefa necessária em aplicações web modernas. Você pode querer executar uma função assíncrona independente no servidor para realizar tarefas como salvar dados no armazenamento de dados, enviar e-mails, baixar PDFs, processar imagens e assim por diante.
O Next.js fornece-nos com Ações do Servidor
que são funções assíncronas que executam no servidor. Podemos usar as ações do servidor para mutações de dados no servidor, mas as ações do servidor podem ser chamadas tanto de componentes do servidor quanto de componentes do cliente.
As ações do servidor são uma ótima maneira de tratar dos envios de formulários executando a ação quando os dados do formulário forem submetidos. Neste artigo, vamos olhar para um caso de uso prático de tratamento de argumentos adicionais em ações de servidor do Next.js.
Se você está interessado em aprender as Ações de Servidor do Next.js com padrões de design e construção de projetos, eu criei um curso rápido para você que você pode encontrar aqui.
Também, este artigo está disponível como um tutorial de vídeo aqui:
Sumário
Por que você precisaria passar argumentos adicionais?
Quando executamos uma ação no servidor num envio de formulário, a ação de servidor obtém automaticamente os dados do formulário. Por exemplo, olhe para o formulário abaixo:
<form className="p-4 flex" action={updateUser}>
<Input className="w-1/2 mx-2" type="text" name="name" />
<Button type="submit">Update User Name</Button>
</form>
Aqui, estamos executando uma ação de servidor chamada updateUser
quando o formulário for submetido. A função updateUser
receberá os dados do formulário submetido como um argumento, que pode ser usado para extrair os valores dos campos do formulário.
Como você vê no snippet de código abaixo, a função updateUser
recebe um formData
como argumento, e nós podemos extrair o valor do campo name
a partir dele.
"use server"
export async function updateUser(formData) {
const name = formData.get('name');
console.log(name);
}
Enquanto este padrão abrange a maioria dos casos de uso básico, você pode precisar passar argumentos adicionais de forma programática para as ações do servidor. Esses argumentos não fazem parte do formulário ou dos dados do formulário ou da entrada de dados do usuário. Elas podem ser valores passados de forma programática para sua ação de servidor.
Para entender isso, veja o trecho de código da ação de servidor abaixo. É a mesma ação de servidor que já vimos antes, mas nós passamos um argumento userId
adicional juntamente com o argumento regular formData
.
"use server"
export async function updateUser(userId, formData) {
const name = formData.get('name');
console.log(userId);
console.log(name);
}
O valor de userId
é algo interno à aplicação – e você não pediria ao usuário para enviar o valor como parte do envio do formulário. Em vez disso, você pode precisar passá-lo de forma programática para sua ação de servidor para executar cálculos adicionais.
Bem, este é o caso de uso de que estamos falando. Enquanto entendemos porque precisamos disso, vamos entender como alcançá-lo. Mas antes, vamos criar um formulário e uma ação de servidor funcional para ele.
Um Formulário Com uma Ação de Servidor
Crie um diretório chamado actions
dentro do diretório app
do seu aplicativo Next.js. Agora crie um arquivo user.js
dentro da pasta actions
com o seguinte código:
"use server"
export async function updateUser(formData) {
const name = formData.get('name');
console.log(name);
// Fazer alguma coisa com o nome, salvar no banco de dados, criar fatura, o que quer que seja!
}
Este é como você cria uma função de servidor em Next.js. Ele deve ter uma diretiva ”use server”
no topo do arquivo para informar ao Next.js que este é um arquivo especial com uma ou mais funções assíncronas a serem executadas no servidor.
Então, temos a ação do servidor (a função assíncrona) updateUser
com formData
como o argumento. Dentro da definição da função, extraímos o valor de name
e imprimimos-no no console.
Agora, vamos anexar essa ação do servidor a um formulário. Para isso, crie uma pasta chamada components
na raiz da pasta do projeto. Crie um arquivo chamado user-form.jsx
com o seguinte código:
import { Input } from "./ui/input"
import { Button } from "./ui/button"
import { updateUser } from "@/app/actions/user"
const UserForm = () => {
return(
<form className="p-4 flex" action={updateUser}>
<Input className="w-1/2 mx-2" type="text" name="name" />
<Button type="submit">Update User Name</Button>
</form>
)
}
export default UserForm;
Isso é um simples componente React com um formulário. O formulário tem um campo de texto de entrada chamado name
e um botão de submissão para enviar o formulário. O formulário tem um atributo action
com a ação do servidor updateUser
como o valor. Agora, quando o formulário for submetido com um valor de name
, a ação do servidor vai recebê-lo como parte dos dados do formulário, conforme discutimos acima.
Vamos testá-lo. Para isso, vamos criar uma rota e página Next.js onde podemos usar o componente UserForm
. Crie uma pasta chamada extra-args
dentro do diretório app
. Agora, crie um arquivo chamado page.js
na pasta app/extra-args
com o seguinte código:
import UserForm from "@/components/user-form";
const ExtraArgsDemo = () => {
return (
<UserForm />
)
}
export default ExtraArgsDemo;
Isso é um simples componente React onde importamos o componente UserForm
e o usamos no JSX. Agora execute o servidor local e acesse essa rota localhost:3000/extra-args
. você deveria ver o formulário com um campo de texto e um botão.
Digite algum texto dentro do campo de texto e clique no botão.
Agora, você será capaz de ver que o texto digitado foi impresso no console do servidor. Por que no console do servidor? Por que não no console do navegador? Isso porque as ações do servidor executam no servidor, e não no lado do cliente do navegador.
Então, com isso, nós agora estabelecemos um fluxo de dados assim:
Página => Formulário => Ação no Servidor
A página tem um formulário. O formulário executa uma ação no servidor quando submetido. A ação no servidor imprime dados de formulário no console do servidor.
Vamos agora melhorar essas partes para passar argumentos adicionais para a ação no servidor.
Como Passar Argumentos Adicionais
Vamos passar uma propriedade ao componente UserForm
da página. Vamos passar um userId
com um valor para fingir que estamos passando este userId programaticamente para nosso formulário e para a ação no servidor a partir daí.
import UserForm from "@/components/user-form";
const ExtraArgsDemo = () => {
return (
<UserForm userId={"1234"} />
)
}
export default ExtraArgsDemo;
No componente UserForm
, nós aceitamos a propriedade userId
. Agora, nós precisamos fazer algo especial para passar este userId para a ação de servidor updateUser
.
O JavaScript tem um método mágico chamado bind()
que nos ajuda a criar uma Função Aplicada Parcialmente
. Com essa função aplicada parcialmente, você pode criar uma função a partir de outra função com argumentos pré-definidos.
No nosso caso, a função `updateUser` já tem um argumento chamado `formData`. Agora, podemos passar `userId` como um argumento adicional usando o método `bind()` para criar uma nova função.
const updatedUserWithId = updateUser.bind(null, userId);
O primeiro argumento do método `bind()` é o contexto ao qual você está associando a função. O contexto gerencia a associação da função com o valor do operador `this`. Em nosso caso, podemos manter como `null` pois não estamos mudando. Depois disso, passamos o novo argumento `userId`. É bom saber que o método `bind()` funciona tanto em componentes do servidor quanto em componentes do cliente.
Aqui está o componente `UserForm` modificado (arquivo `user-form.jsx`). Note que o valor de ação do formulário agora é modificado para a nova função `updatedUserWithId`.
import { Input } from "./ui/input"
import { Button } from "./ui/button"
import { updateUser } from "@/app/actions/user"
const UserForm = ({userId}) => {
const updatedUserWithId = updateUser.bind(null, userId);
return(
<form className="p-4 flex" action={updatedUserWithId}>
<Input className="w-1/2 mx-2" type="text" name="name" />
<Button type="submit">Update User Name</Button>
</form>
)
}
export default UserForm;
Agora, a ação do servidor receberá o valor de `userId` como um argumento. Vamos imprimir isso no console também.
"use server"
export async function updateUser(userId, formData) {
const name = formData.get('name');
console.log(userId);
console.log(name);
// Fazer qualquer coisa com o user id e nome, salvar no BD,
// criar fatura, o que quer que seja!
}
Se você submeter o formulário com um valor de nome:
Você verá que ambos os valores de `userId` e `name` são enviados para o console do servidor. Ótimo! Nós registramos um valor do formulário e o outro foi passado internamente para a ação do servidor.
Então, aprendemos como passar argumentos extras para a ação do servidor juntamente com os dados do formulário.
E então, o que é feito com os campos ocultos?
HTML suporta um campo de formulário do tipo oculto para passar dados do cliente para o servidor sem aceitar a entrada dos usuários. Então isso significa que poderíamos ter usado o campo oculto para passar o valor do userId
assim:
Então por que fizemos tudo isso com o método bind()
? Bem, por causa de preocupações de segurança. Quando você passa dados usando campos ocultos, o valor fará parte do HTML renderizado e não será codificado também. Portanto, é melhor lidar com isso programaticamente.
Recursos
É isso por enquanto. Você gostou de ler este artigo e aprendeu algo novo? Se sim, eu adoraria saber se o conteúdo foi útil. Vou compartilhar alguns recursos adicionais que você pode precisar:
-
Todo o código-fonte usado neste artigo está no meu GitHub.
-
Aqui está o Curso Crash Course de Ação do Servidor com Padrões e Projeto.
-
Aqui está a Documentação Oficial de Ação do Servidor se você quiser ler mais.
-
E você pode ler mais sobre o método bind() aqui.
Além disso, você pode me conectar por:
-
Assinando minha Conta do YouTube. Se você estiver disposto a aprender
React
e seu ecossistema, comoNext.js
, com conceitos básicos e projetos, tenho boas notícias para você: você pode ver essa playlist na minha conta do YouTube com 25+ tutoriais de vídeo e 15+ horas de conteúdo engajante até agora, de graça. Espero que você goste deles também. -
Seguir comigo em X (Twitter) ou LinkedIn se você não quiser perder a dose diária de dicas de aprimoramento.
-
Verificar e seguir meu trabalho de código aberto no GitHub.
-
Eu publico regularmente postagens significativas no meu GreenRoots Blog, você pode achar que são úteis também.
Vejo você logo com meu próximo artigo. Até então, por favor, cuide de si mesmo e continue aprendendo.
Source:
https://www.freecodecamp.org/news/how-to-pass-additional-arguments-to-nextjs-server-actions/