Desenvolvimento
Desenvolvimento Web
4 de novembro de 2019 às 15:30
Implementando adicionar e remover itens de listas em tempo de execução.
Tempo de leitura: 5 minutos
Fala galera! depois de algum tempo sem postar, eu estou de volta!
Dessa vez vou falar sobre a implementação de listas dinâmicas utilizando o ReactJS, o termo lista dinâmica vai ser muito usado neste post, então vou começar definindo-o:
Uma lista dinâmica como o nome diz é uma lista que pode ser alterada pelo usuário, podemos concretizar o termo com uma lista de tarefas, onde cada tarefa possui nome e data e o usuário pode adicionar ou remover tarefas, sem afetar os outros itens da lista;
Diferente das outras vezes, vou utilizar create-react-app, vou prezar pela simplicidade e não vou utilizar outras bibliotecas nem mesmo styled-components, mas caso você vá utilizar o react em uma aplicação maior, recomendo que utilize React com webpack e styled-components.
Pré requisitos e conhecimentos prévios desejáveis:
Estou considerando neste post que você já sabe sobre layout e, também, como criar um projeto em React-Native, dito isto, será ignorada toda a parte de criação e configuração do projeto.
- ReactJS
- Layout com FlexBox
- Arrays com JavaScript
Primeiro vamos criar e executar o projeto com:
$ npx create-react-app dynamic-list-itens
$ yarn start
Criando os componentes
Em seguida vamos criar um componente que irá servir para exibir cada item na lista, vou ignorar todo o css no artigo, mas você pode pegar o css a partir do repositório no final do artigo.
import React from 'react';
const ListItem = ({ onChange, onDelete, value }) => {
return (
<div className="Item-container">
<input
className="Item-field"
value={value}
onChange={onChange}
/>
<button onClick={onDelete}>Excluir</button>
</div>
);
};
export default ListItem;
Basicamente este componente precisará disparar dois eventos para o elemento pai: o evento de edição e o evento de exclusão, para isso criei duas props: onChange e onDelete, também uma prop para receber o nome atual da tarefa: value. De resto é um componente bem simples.
Agora vamos criar um novo componente responsável pela criação de novas tarefas:
import React, { useState } from 'react';
const NewTaskInput = ({ onSubmit }) => {
const [newItem, setNewItem] = useState('');
function setNewTask({target}) {
setNewItem(target.value);
}
function submit(e) {
e.preventDefault();
onSubmit(newItem);
}
return (
<div>
<form onSubmit={submit}>
<input
className="Todo-input"
placeholder="Digite uma nova tarefa"
onChange={setNewTask}
/>
<button type="submit">
Adicionar
</button>
</form>
</div>
)
};
export default NewTaskInput;
Outro componente bem simples, esse irá disparar apenas um evento para o elemento pai: o evento para adicionar a nova tarefa. Esse componente mantém um estado interno com o valor do input e repassa esse valor através do evento onSubmit. Note que usei um form, fiz isso para que seja possível adicionar a tarefa pressionando enter. note também que na função submit eu estou chamando o preventDefault do disparo do form, para impedir que a página seja recarregada após o envio.
Vamos agora à criação do Component que irá conter o que acabamos de criar, esse componente será o responsável por manter o array que irá conter as tarefas, exclusão de uma tarefa e por atualizar uma tarefa também.
import React, { useState } from 'react';
import './App.css';
import ListItem from './components/ListItem'
import NewTaskInput from './components/NewTaskInput'
const App = () => {
const [tasks, setTasks] = useState([]);
function addNewTask(task) {
const itensCopy = Array.from(tasks);
itensCopy.push({id: tasks.length, value: task});
setTasks(itensCopy);
}
function updateTask({target}, index) {
const itensCopy = Array.from(tasks);
itensCopy.splice(index, 1, { id: index, value: target.value });
setTasks(itensCopy);
}
function deleteTask(index) {
const itensCopy = Array.from(tasks);
itensCopy.splice(index, 1);
setTasks(itensCopy);
}
return (
<div className="App">
<div className="App-header">
<NewTaskInput onSubmit={addNewTask} />
{tasks.map(({id, value}, index) => (
<ListItem
key={id}
value={value}
onChange={(event) => updateTask(event, index)}
onDelete={() => deleteTask(index)}
/>
))}
</div>
<div className="Array-preview">
<pre>
{JSON.stringify(tasks, null, 4)}
</pre>
</div>
</div>
)
}
export default App;
Como havia dito este componente mantém um estado interno que é o Array contendo as nossas tarefas.
Existem também três funções: addNewTask, deleteTask e updateTask:
Em todas as funções eu não vou editar o Array do estado diretamente, pois estaria inflingindo uma regra importante do React: não mutar o estado diretamente. Sendo assim vou sempre criar uma cópia do Array, usando Array.from.
O método Array.from() cria uma nova instância de um Array quando for passado um array-like ou um iterable object como argumento. https://developer.mozilla.org/pt-BR/docs/Web/JavaScript/Reference/Global_Objects/Array/from
Lógica para adicionar, atualizar e excluir tarefas.
addNewTask Essa é a função mais simples responsável apenas por adicionar novas tarefas, nela eu recebo o paramêtro task do evento onSubmit do nosso component NewTaskInput, crio a cópia do Array de tarefas atual, insiro minha nova tarefa com o método push, usando como id o length do array e como value o paramêtro task, por fim atualizo meu estado com a cópia do Array.
updateTask Para atualizar uma tarefa também é bem simples, eu recebo o paramêtro index para indicar qual elemento quero atualizar após isso vou utilizar o método splice,
O método splice altera o conteúdo de um Array, adicionando novos elementos enquanto remove elementos antigos, ou somente removendo elementos. https://developer.mozilla.org/pt-BR/docs/Web/JavaScript/Reference/Global_Objects/Array/splice
deleteTask Para excluir uma tarefa é basicamente a mesma coisa, utilizo o mesmo método splice porem sem o último argumento, já que neste caso não estou substituindo apenas excluindo.
E este é o resultado final:
Este é o link do projeto no github caso queira modificar a partir dele: https://github.com/digital-heroes/dynamic-list-itens
É isso galera! foi um prazer enorme tomar um pouco do seu tempo. Espero que o post tenha ajudado bastante.
Obrigado pela leitura e até o próximo post!