Translate
Поиск по этому блогу
пятница, 29 марта 2019 г.
четверг, 28 марта 2019 г.
Raect приложение с MLabDB ( II).
На этом этапе у нас есть приложение, которое не сохраняет внесенные изменения в базу данных MLab.
Давайте научим его делать это.
Внесение изменений в базу данных (checked)
Первое, что мы сделаем, это зададим в файле App.css класс, который будет добавляться к каждому таску, если у негоchecked: true
и будет делать текст зачеркнутым.
.completed { text-decoration: line-through; }
Теперь применим этот класс к компоненту. Для того, чтобы это сработало мы создадим функцию, которая будет срабатывать на событие
onChange
, привяжем ее к this
и конкретному таску, чтобы была возможность отследить изменения.
TaskItem.js
import React, { Component } from "react"; import { Checkbox } from "muicss/react"; class TaskItem extends Component { constructor(props) { super(props) this.state = { task: props.task } } onChange(task, e) { this.props.onEditState(task, e.target.checked); } render() { return <div className="mui--divider-bottom"> <Checkbox className={(this.state.task.completed) ? "completed" : ""} onChange={this.onChange.bind(this, this.state.task)} name={this.state.task._id.$oid} label={this.state.task.text} defaultChecked={this.state.task.completed} /> </div>; } } export default TaskItem;
Так как у нас все взаимодействия с базой идут из файла App.js, то нам нужно оттуда и передавать данные в базу, поэтому поднимаемся на уровень выше - к родителю Tasks.js.
Здесь мы создадим функцию
handleEditState(task, checked)
, которая принимает два параметра, а именно таск и отмеченный и передадим ее в компонент TaskItem.js, где мы ее написали внутри функции onChange
.
import React, { Component } from 'react'; import { Panel } from 'muicss/react'; import TaskItem from './TaskItem'; class Tasks extends Component { handleEditState(task, checked) { this.props.onEditState(task, checked) } render() { let taskItems; if (this.props.tasks) { taskItems = this.props.tasks.map(task => { return ( <TaskItem onEditState={this.handleEditState.bind(this)} key={task._id.$oid} task={task} /> ) }) } return ( <Panel> {taskItems} </Panel> ); } } export default Tasks;
И теперь, наконец-то создадим самое основное в родителе - App.js
Вначале мы создадим саму функцию
editState(task,checked){ console.log(task); }
теперь передадим ее компоненту:
<Tasks onEditState={this.editState.bind(this)} ...
И если сейчас посмотреть в консоли приложения, то в момент, когда мы отмечаем чекбокс, мы видим в консоли все данные таска:
Если в консоль вывести параметр чекед, то мы увидим следующее:
Таким образом, мы убедились, что в функцию приходят именно те данные, которые нам нужны.
Теперь наша задача внести изменения в базу.
Для этого мы воспользуемся опять
axios
, почти как при получении данных, но с некоторым отличием в URL, туда нам нужно передать идентификатор отмеченного бокса, чтобы внести изменения именно в нужный таск.
Обратите внимание, что в строку мы вставляем JS-код обычным сложением строк - конкатенацией.
"https://api.mlab.com/api/1/databases/react-tasks/collections/tasks/" + task._id.$oid + "?apiKey=yourAPIkey"
Метод запроса будет уже
put
. Передаем данные data
. Создаем временную переменную let tasks
, проходим циклом по всем таскам и если есть соответсвие по идентификатору, то меняем значение нужного таска completed
на checked
И на основании этого изменяем состояние компонента:
this.setState({ tasks: tasks });
Приведу код полностью
import React, { Component } from 'react';
import { Appbar, Container } from 'muicss/react';
import axios from 'axios';
import Tasks from './Components/Tasks';
import './App.css';
class App extends Component {
constructor() {
super()
this.state = {
tasks: []
}
}
componentWillMount() {
this.getTasks();
}
getTasks() {
axios
.request({
method: "get",
url:
"https://api.mlab.com/api/1/databases/react-tasks/collections/tasks?apiKey=yourAPIkey"
})
.then(response => {
this.setState(
{
tasks: response.data
},
() => {
console.log(this.state);
}
);
})
.catch(error => {
console.log(error);
});
}
editState(task, checked) {
axios
.request({
method: "put",
url:
"https://api.mlab.com/api/1/databases/react-tasks/collections/tasks/" + task._id.$oid + "?apiKey=yourAPIkey",
data: {
text: task.text,
completed: checked
}
}).then((response) => {
let tasks = this.state.tasks;
for (let i = 0; i < tasks.length; i++) {
if (tasks[i]._id.$oid === response.data._id.$oid) {
tasks[i].completed = checked;
}
}
this.setState({ tasks: tasks });
}).catch(error => {
console.log(error);
});
}
render() {
return (
<div className="App">
<Appbar>
<Container>
<table width="100%">
<tbody>
<tr>
<td className="mui--appbar-height">
<h3>React Tasks</h3>
</td>
</tr>
</tbody>
</table>
</Container>
</Appbar>
<br />
<Container>
<Tasks
onEditState={this.editState.bind(this)}
tasks={this.state.tasks}
/>
</Container>
</div>
);
}
}
export default App;
Теперь мы можем посмотреть в консоль и убедиться, если мы все сделали правильно, то при отметке чекбокса, у нас будет появляться зачеркнутый текст и такое же состояние будет при обновлении страницы.
Ниже на фото вы можете увидеть, что все изменения чекбокса успешно попадают в базу.
Слева - браузер, справа - база данных MLab.
Таким образом мы получили сохранение изменений при отметке чекбокса в базу данных MLab (mongodb).
Да и еще, я уже писал про сохранение ключей в безопасном месте и поэтому я вам рекомендую хранить их в отдельном файле.
Например keys/apiKeys.js в переменной:
export const apiKey = 'ВАШ_КЛЮЧ_API';
и получать их в App.js импортом -
import {apiKey} from './keys/apikeys';
Это позволит легко добавить ключи в .gitignore и они не попадут, даже случайно, в "нечистые руки".
Код на данном этапе доступен по ссылке: react-mui-mlab-abc
ci -m "Transfer of changes to the database and their preservation."
Создание формы добавления задачи.
В папке компонентов для этого создадим отдельный файл AddTask.js Все содержимое приведу полностью, чтобы вы могли сразу понять, что в нем нет ничего необычного или достойного отдельного объяснения.import React, { Component } from "react"; import { Form, Input } from "muicss/react"; class AddTask extends Component { constructor(props) { super(props) this.state = { task: '' } } onSubmit(e) { this.props.onAddTask(this.state.task); e.preventDefault(); } onChange(e) { this.setState({ task: e.target.value }) } render() { return <div className="mui--divider-bottom"> <Form onSubmit={this.onSubmit.bind(this)}> <Input hint="Add Task" onChange={this.onChange.bind(this)} /> </Form> </div>; } } export default AddTask;
Поля
Form
и Input
из библиотеки MUI.
На поле ввода повесили событие на изменение его содержимого. В функции
onChange
сразу сохраняем изменения в стейт.
Кнопкой запустим функцию добавления задачи -
onAddTask
, куда и передадим значение стейта.
Функцию получим в
props
, поэтому мы ее создадим позже в родителе - App.js из которого и будем взаимодействовать с базой данных.
Теперь идем в файл App.js и импортируем в него вновь созданный компонент:
import AddTask from './Components/AddTask';
Выведем его на страницу сразу после Контейнера. Передадим ему как свойство функцию
addTask
и создадим ее сразу над render()
. Пока что выведем в нее значение переменной text
:
import React, { Component } from 'react'; import { Appbar, Container, Button } from 'muicss/react'; import axios from 'axios'; import Tasks from './Components/Tasks'; import AddTask from './Components/AddTask'; import './App.css'; import { apiKey } from './keys/apikeys'; class App extends Component { constructor() { super() this.state = { tasks: [] } } componentWillMount() { this.getTasks(); } getTasks() { axios .request({ method: "get", url: "https://api.mlab.com/api/1/databases/react-tasks/collections/tasks?apiKey=" + apiKey }) .then(response => { this.setState( { tasks: response.data }, () => { console.log(this.state); } ); }) .catch(error => { console.log(error); }); } editState(task, checked) { axios .request({ method: "put", url: "https://api.mlab.com/api/1/databases/react-tasks/collections/tasks/" + task._id.$oid + "?apiKey=" + apiKey, data: { text: task.text, completed: checked } }).then((response) => { let tasks = this.state.tasks; for (let i = 0; i < tasks.length; i++) { if (tasks[i]._id.$oid === response.data._id.$oid) { tasks[i].completed = checked; } } this.setState({ tasks: tasks }); }).catch(error => { console.log(error); }); } addTask(text) { console.log(text); } render() { return ( <div className="App"> <Appbar> <Container> <table width="100%"> <tbody> <tr> <td className="mui--appbar-height"> <h3>React Tasks</h3> </td> </tr> </tbody> </table> </Container> </Appbar> <br /> <Container> <AddTask onAddTask={this.addTask.bind(this)} /> <Tasks onEditState={this.editState.bind(this)} tasks={this.state.tasks} /> </Container> </div> ); } } export default App;
Если посмотреть на то, что получилось в браузере, то мы можем ввести какой-либо текст, нажать Enter и в консоли увидим это же значение:
Запрос на добавление данных в базу.
Все что нам нужно это написать функцию, которая будет взаимодействовать с базой при помощиaxios
Пишем простой запрос. Указываем метод
post
, немного изменяем URL (это можно посмотреть в данных базы. Об этом рассказывал в первой части.).
Далее пишем данные, которые будем передавать.
Во временную переменную сохранили то что было в стейте до этого. Добавили методом
push
новые данные.
В данных
completed: false
, потому что мы предполагаем, что изначально задание не сделано.
При успешном выполнении вносим изменения в стейт.
В случае ошибки - поймали ее и вывели в консоль. Это если коротко...
addTask(text) { axios .request({ method: "post", url: "https://api.mlab.com/api/1/databases/react-tasks/collections/tasks?apiKey=" + apiKey, data: { text: text, completed: false } }).then((response) => { let tasks = this.state.tasks; tasks.push({ _id: response.data._id, text: text, completed: false }) this.setState({ tasks: tasks }); }).catch(error => { console.log(error); }); }
Посмотрим в браузер:
Вводим какой-либо текст. Нажимаем Enter и видим обновление данных на странице без перезагрузки и, соответственно данных в базе.
Для того, чтобы в этом убедиться, можно просто перезагрузить страницу и мы получим те же "новые" данные.
Код на данном этапе доступен по ссылке: react-mui-mlab-abc
ci -m "Added task to DataBase"
Добавление кнопки удаления выполненных заданий.
Начнем с тобой, что добавим саму кнопку в компонент.В импорт из MUI добавим импорт кнопки:
import { Appbar, Container, Button } from 'muicss/react';
И прямо над закрывающим тегом контейнера, выведем саму кнопку удаления. Добавим ей красный цвет.
На клик повесим функцию, которую сейчас же и создадим.
<Container>
<AddTask onAddTask={this.addTask.bind(this)} />
<Tasks
onEditState={this.editState.bind(this)}
tasks={this.state.tasks}
/>
<Button color="danger" onClick={this.clearTasks.bind(this)} >
Clear Tasks
</Button>
</Container>
Посмотрим в браузере:
Сделаем кнопку работающей.
Функция
clearTasks
Во временную переменную
tasks
, получим все задания из состояния.
Для удобства, кол-во заданий вынесем в отдельную переменную -
i
Пройдем по всем заданиям циклом
while
от большего к меньшему и если оно выполнено (completed
), то методом splice
уберем его из массива.
Здесь же внесем изменения в базу методом
delete
Для работы с базой данных MongoDB нам нужен доступ не просто по идентификатору, а по
_id.$oid
Ответ - стандартное подтверждение удаления и ошибку ловим в консоль.
clearTasks() { let tasks = this.state.tasks; let i = tasks.length; while (i--) { if (tasks[i].completed === true) { let id = tasks[i]._id.$oid; tasks.splice(i, 1); axios.request({ method: 'delete', url: "https://api.mlab.com/api/1/databases/react-tasks/collections/tasks/" + id + "?apiKey=" + apiKey, }).then(response => { }).catch((error) => { console.log(error) }) } } this.setState({ tasks: tasks }) }
Теперь вы сможете не только добавить новые задачи, но и отметить выполненные, и при необходимости их удалить.
Проверяем:
Код на данном этапе доступен по ссылке: react-mui-mlab-abc
ci -m "Delete completed tasks from DataBase"
Можно еще порефакторить код. Сделать автоматическую очистку поля при добавлении задачи и многое другое. Можно вообще, переписать код в виде функциональных компонентов используя современные возможности хуки и пр.
К примеру, для очистки поля ввода можно сделать так.
- К самой форме ввода добавить
id
- компонент<Form id="form"/ >
- В функцию отправки
onSubmit
, добавить строку очистки всей формы:document.getElementById("form").reset();
onSubmit(e){
this.props.onAddTask(this.state.task);
e.preventDefault();
document.getElementById("form").reset();
}
Данный проект в постах, можно рассматривать, скорее как учебный. Здесь все понятно. Я специально не пытался сокращать код, именно для его понимания и простоты.
Спасибо тем. кто дочитал до конца и
...Happy Coding!
вторник, 26 марта 2019 г.
Raect приложение с MLabDB ( I ).
Сегодня напишем простое приложение, которое будет взаимодействовать с базой данных MLab.
Приложение будет простое. Оно будет состоять из списка задач. Главное чем оно будет отличаться от обычного ToDo React-приложения, это возможностью сохранения данных после перезагрузки (открытия заново) нашего приложения.
Готовое приложение вы можете посмотреть на хостинге здесь.
Приступим.
Если вы уже работали с этим сервисом, то тогда нажимаем кнопку "Create New" и создаем новую базу (документ).
Назовем ее (его), предположим, так -
Добавляем пользователя для БД, вводим пароль. Галочку - "Только чтение" не ставим!
Все данные сохраняем себе в блокнот.
Теперь создаем коллекцию - Add Collection
Далее нажимаем - Add Document
Данные в коллекцию добавим такие:
Обратите внимание, что значение boolean без кавычек. Фото ниже:
Вы можете добавить свои данные, в поля
Нажимаем кнопку "Create and go back"
Таким же образом мы введем и вторую задачу.
Теперь мы имеем базу с двумя заданиями.
Сразу после его установки, нам нужно перейти в него в КС и установить дополнительные модули:
После завершения утстановки, мы можем запустить наше приложение:
Обычное готовое приложение реакт запустится на порту 3000.
Не забываем подключить и линк к public/index.html
Его я взял с сайта MUI и от туда же возьмем готовый appbar . Уберем у него все лишнее и получим:
И следуя подсказки из консоли завернем все в контейнер:
Ниже, внутри div, сделаем отступ и в контейнере напишем вывод нового компонента
App.js
В папке src создадим папку Components, а в ней файл компонента - Tasks.js. В нем мы импортируем
Tasks.js
Посмотрим в браузере:
Код на данном этапе доступен по ссылке: react-mui-mlab-abc
ci -m "Create Navbar and Tasks Component"
(ci -m - коммит. В данном случае смотрите коммит - Retrieving data and outputting it in a component).
Для этого, вам нужно выполнить следующие действия:
В правом верхнем углу аккаунта вы увидите нечто похожее:
{ user: "Имя Пользователя", account: "Псевдоним" }
нажимаем на поле
попадем на страницу, где есть ваш ключ :
Ключ копируем и можно сохранить.
Более подробно можно прочитать на официальном сайте - API Authentication.
Более подробно о жизненных циклах React-компонентов я писал в посте - React.js (6) Жизненный цикл компонентов.
Идем в файл App.js и создадим там функцию -
Не забываем подключить
Вызовем функцию поучения наших заданий в жизненном цикле компонента и сохраняем полученные данные в стейт.
Добавили вывод в консоль стейта.
App.js
Более подробно о работе с API MLab
Смотрим в браузере. В консоли мы увидим, все наши таски:
Для вывод каждого отдельного компонента (таска) мы создадим отдельный компонент -
Здесь ничего сложного. Мы передадим в этот компонент уже одну конкретную задачу из его родителя и выведем ее на экран в виде чекбокса с именем ( для этого используем идентификатор для каждого компонента -
Родительскому
Теперь нам нужно в теле самого компонента
Для этого в методе
Tasks.js
Если посмотреть в браузере. то можно увидеть:
Теперь у нас есть те компоненты, которые мы создавали в БД на сервере MLab.
Давайте проделаем уже знакомые нам действия и добавим в базу третий таск с состоянием
Добавляем.
И теперь у нас в базе три таска:
Перезагружаем браузер и...
Таким образом мы с вами получили доступ к БД MLab по API и вывели данные в React - приложение, стилизованное MUI.
Код на данном этапе доступен по ссылке: react-mui-mlab-abc
ci -m "Retrieving data and outputting it in a component"
В следующем посте я расскажу вам, как сохранять данные в базе и много другого не менее интересного.
Приложение будет простое. Оно будет состоять из списка задач. Главное чем оно будет отличаться от обычного ToDo React-приложения, это возможностью сохранения данных после перезагрузки (открытия заново) нашего приложения.
Готовое приложение вы можете посмотреть на хостинге здесь.
Приступим.
Создаем базу данных на сервисе MLab
О регистрации и первых шагах по созданию базы данных, я многократно рассказывал в своих постах. Более подробно, вы можете посмотреть в посте - Блог на NodeJS Express MongoDB ( I ).Если вы уже работали с этим сервисом, то тогда нажимаем кнопку "Create New" и создаем новую базу (документ).
Назовем ее (его), предположим, так -
react-tasks
.
Добавляем пользователя для БД, вводим пароль. Галочку - "Только чтение" не ставим!
Все данные сохраняем себе в блокнот.
Теперь создаем коллекцию - Add Collection
Далее нажимаем - Add Document
Данные в коллекцию добавим такие:
{ "text":"My Task One", "completed": false }
Обратите внимание, что значение boolean без кавычек. Фото ниже:
Вы можете добавить свои данные, в поля
text
и completed
.
Нажимаем кнопку "Create and go back"
Таким же образом мы введем и вторую задачу.
Теперь мы имеем базу с двумя заданиями.
Создание приложения
Открываем КС (командую строку, если вы на винде, как и я) или другим способом в нужной директории создаем само Реакт-приложение. Для этого будем использовать готовое решение - create-react-app.
create-react-app reacttasks
reacttasks
- название самого приложения.
Сразу после его установки, нам нужно перейти в него в КС и установить дополнительные модули:
cd reacttasks
npm install --save muicss axios
npm install --save muicss axios
После завершения утстановки, мы можем запустить наше приложение:
npm start
Обычное готовое приложение реакт запустится на порту 3000.
Удаляем лишнее
Удалим logo.svg, в файле App.css - всё содержимое, а в App.js все что внутри<div className="App">
. Там мы что-нибудь напишем. например - My App. Это нужно только для того, чтобы убедиться сразу, что мы все сделали правильно. В браузере мы увидим эту надпись.
Добавляем Appbar
В самом верху, после импорта реакт, импортируем MUI :import { Appbar, Container } from 'muicss/react';
Не забываем подключить и линк к public/index.html
<link href="//cdn.muicss.com/mui-0.9.41/css/mui.min.css" rel="stylesheet" type="text/css" media="screen" />
Его я взял с сайта MUI и от туда же возьмем готовый appbar . Уберем у него все лишнее и получим:
И следуя подсказки из консоли завернем все в контейнер:
import React, { Component } from 'react'; import { Appbar, Container } from 'muicss/react'; import './App.css'; class App extends Component { render() { return ( <div className="App"> <Appbar> <Container> <table width="100%"> <tbody> <tr> <td className="mui--appbar-height"> <h3>React Tasks</h3> </td> </tr> </tbody> </table> </Container> </Appbar> </div> ); } } export default App;
Ниже, внутри div, сделаем отступ и в контейнере напишем вывод нового компонента
<Tasks />
и сразу его импортируем в наш файл App.js
import Tasks from './Components/Tasks';
App.js
import React, { Component } from 'react'; // Access all components from `muicss/react` module import { Appbar, Container } from 'muicss/react'; import Tasks from './Components/Tasks'; import './App.css'; class App extends Component { render() { return ( <div className="App"> <Appbar> <Container> <table width="100%"> <tbody> <tr> <td className="mui--appbar-height"> <h3>React Tasks</h3> </td> </tr> </tbody> </table> </Container> </Appbar> <br /> <Container> <Tasks /&gr; </Container> </div> ); } } export default App;
В папке src создадим папку Components, а в ней файл компонента - Tasks.js. В нем мы импортируем
Panel
из MUI, и выведем просто слово TASKS.
Tasks.js
import React, { Component } from 'react'; import { Panel } from 'muicss/react'; class Tasks extends Component { render() { return (TASKS ); } } export default Tasks;
Посмотрим в браузере:
Код на данном этапе доступен по ссылке: react-mui-mlab-abc
ci -m "Create Navbar and Tasks Component"
(ci -m - коммит. В данном случае смотрите коммит - Retrieving data and outputting it in a component).
API MLab
В дальнейшем нам для работы потребуется получить доступ к API MLab по ключу.Для этого, вам нужно выполнить следующие действия:
В правом верхнем углу аккаунта вы увидите нечто похожее:
{ user: "Имя Пользователя", account: "Псевдоним" }
нажимаем на поле
user
{ user: "Имя Пользователя", account: "Псевдоним" }
попадем на страницу, где есть ваш ключ :
Обязательно обратите внимание, чтобы доступ по ключу был разрешен - на фото эта кнопка, ниже вашего ключа!
Ключ копируем и можно сохранить.
Более подробно можно прочитать на официальном сайте - API Authentication.
В целях безопасности храните ключ в тайне. Не давайте злоумышленникам получить доступ к вашим БД!
Получение данных от MLab по API
Сейчас наша задача состоит в том. чтобы получить данные, которые мы сохранили в базу на предварительном этапе. Это лучше всего сделать в компоненте жизненного цикла -componentWillMount()
Более подробно о жизненных циклах React-компонентов я писал в посте - React.js (6) Жизненный цикл компонентов.
Идем в файл App.js и создадим там функцию -
getTasks()
, которой мы будем обращаться к API MLab и получать данные.
Не забываем подключить
axios
.
Вызовем функцию поучения наших заданий в жизненном цикле компонента и сохраняем полученные данные в стейт.
Добавили вывод в консоль стейта.
App.js
import React, { Component } from 'react'; // Access all components from `muicss/react` module import { Appbar, Container } from 'muicss/react'; import axios from 'axios'; import Tasks from './Components/Tasks'; import './App.css'; class App extends Component { constructor() { super() this.state = { tasks: [] } } componentWillMount() { this.getTasks(); } getTasks() { axios .request({ method: "get", url: "https://api.mlab.com/api/1/databases/react-tasks/collections/tasks?apiKey=yourAPIkey" }) .then(response => { this.setState( { tasks: response.data }, () => { console.log(this.state); } ); }) .catch(error => { console.log(error); }); } render() { return ( <div className="App"> <Appbar> <Container> <table width="100%"> <tbody> <tr> <td className="mui--appbar-height"> <h3>React Tasks</h3> </td> </tr> </tbody> </table> </Container> </Appbar> <br /> <Container> <Tasks /> </Container> </div> ); } } export default App;
Более подробно о работе с API MLab
Смотрим в браузере. В консоли мы увидим, все наши таски:
Вывод данных на страницу.
Теперь мы можем передать полученные данные, как обычное состояние, дочернему компоненту. В данном случае -<Tasks tasks={this.state.tasks}/>
Для вывод каждого отдельного компонента (таска) мы создадим отдельный компонент -
TaskItem
.
import React, { Component } from "react"; import { Checkbox } from "muicss/react"; class TaskItem extends Component { constructor(props) { super(props) this.state = { task: props.task } } render() { return <div className="mui--divider-bottom"> <Checkbox name={this.state.task._id.$oid} label={this.state.task.text} defaultChecked={this.state.task.completed} /> </div>; } } export default TaskItem;
Здесь ничего сложного. Мы передадим в этот компонент уже одну конкретную задачу из его родителя и выведем ее на экран в виде чекбокса с именем ( для этого используем идентификатор для каждого компонента -
_id.$oid
)
Родительскому
div
дадим класс с нижним подчеркиванием для красоты из MUI. В значение label
выведем текстовое значение, а сделано\не сделано - как значение true \ false
поля - completed
.
Теперь нам нужно в теле самого компонента
Tasks
воспользоваться методом map()
и передать в TaskItem
одну задачу.
Для этого в методе
render
компонента создадим пустую переменную - let taskItems;
.
Ниже проверим - Если пропсы пришли, то в эту переменную вернем наш компонент для каждого таска с данными. Эти данные для каждого отдельного компонента мы получаем методом map()
.
Tasks.js
import React, { Component } from "react"; import { Panel } from "muicss/react"; import TaskItem from "./TaskItem"; class Tasks extends Component { render() { let taskItems; if (this.props.tasks) { taskItems = this.props.tasks.map(task => { return <TaskItem key={task._id.$oid} task={task} />; }); } return <Panel>{taskItems}</Panel>; } } export default Tasks;
Если посмотреть в браузере. то можно увидеть:
Теперь у нас есть те компоненты, которые мы создавали в БД на сервере MLab.
Давайте проделаем уже знакомые нам действия и добавим в базу третий таск с состоянием
"completed": true
Добавляем.
И теперь у нас в базе три таска:
Перезагружаем браузер и...
Таким образом мы с вами получили доступ к БД MLab по API и вывели данные в React - приложение, стилизованное MUI.
Код на данном этапе доступен по ссылке: react-mui-mlab-abc
ci -m "Retrieving data and outputting it in a component"
В следующем посте я расскажу вам, как сохранять данные в базе и много другого не менее интересного.
вторник, 26 февраля 2019 г.
React + Webpack 4 + Babel 7 Руководство по установке.
Это руководство для тех, кто ищет свои способы настройки среды React, Webpack и Babel.
Это руководство относится к последним версиям React 16, Webpack 4 и Babel 7.
Facebook создал и поддерживает готовое приложение - creat-react-app, которое уже включает все необходимые настройки и отлично подходит для начинающих разработчиков.
Эта статья больше о том, как научить людей настраивать собственный проект без стороннего шаблонного проекта. В какой-то момент вы начнете использовать инструменты вокруг вашей библиотеки или фреймворка по вашему выбору. В JavaScript вам придется иметь дело с Webpack, Babel и многим другим, и поэтому имеет смысл узнать о них. Я надеюсь, что эта статья поможет вам в этом приключении.
Результат:
Если не установлены, то установите с официального сайта.
Я работаю под Windows -8 и в редакторе VS-Code.
Перейдите в нужную вам директорию и создайте основную папку для вашего проекта. У меня это будет папка react-min-setup
Выше, я создал папку из КС ( командной строки) и перешел в нее. Теперь у вас есть папка проекта. Далее вы можете инициализировать его как проект npm . Задав ему
Вы можете извлечь файл package.json после инициализации вашего проекта как проекта npm. Он должен быть заполнен вашими значениями по умолчанию. Если вы хотите изменить настройки по умолчанию, вы можете просмотреть и изменить их с помощью следующих команд в командной строке:
После настройки вашего проекта npm, вы можете установить пакеты узлов (библиотеки) в свой проект с помощью самого npm. После установки нового пакета узла, он должен появиться в вашем файле package.json .
Я это сделаю из терминала редактора.
В папке проекта я создам папку dist с файлом index.html. В этой папке будут храниться уже готовые для размещения на хостинге, или иного использования, файлы проекта.
index.html
В файле ничего особенного. Есть корневой див, в котором будет размещаться весь React - проект и подключен файл bundle.js из этой же папки dist, в который и будут собираться все файлы нашего проекта, с помощью webpack.
Два важных факта о содержании:
файл bundle.js будет сгенерирован Webpack
Атрибут
Поэтому наши следующие возможные шаги:
На этом этапе все файлы проекта доступны в гит-репо react-min-setup-abc ci -m "Initiall commit layout project"
Из корневой папки:
Теперь у вас должна быть папка node_modules, где вы можете найти сторонние зависимости. Зависимости также будут перечислены в файле package.json , так как вы использовали флаг
Структура папки:
В файле package.json вы можете добавить стартовый скрипт (выделил красным) дополнительно к заданным по умолчанию скриптам для запуска webpack-dev-server.
package.json
В файле появились установленные зависимости:
Сценарий определяет, что вы хотите использовать webpack-dev-server с файлом конфигурации с именем webpack.config.js .
Давайте создадим необходимый файл webpack.config.js .
Грубо говоря, в конфигурационном файле сказано, что:
В нашем проекте отсутствует папка и файл src / index.js . Создадим их. В файл index.js добавим, какой - нибудь вывод в консоль. Например:
Структура проекта:
Теперь вы сможете запустить свой webpack-dev-server.
По умолчанию, проект запустится на порту 8080. И если посмотрим в консоль, то увидим наше сообщение.
Сейчас, вы подаете свое приложение через Webpack прямо в браузер. Вы связываете файл точки входа src / index.js как bundle.js , используете его в dist / index.html и можете увидеть его console.log()в консоли разработчика.
Пока это только файл src / index.js . Но позже вы импортируете больше файлов JS в этот файл, который автоматически будет упакован Webpack в файл bundle.js, который и будет создан.
На этом этапе все файлы проекта доступны в гит-репо react-min-setup-abc
ci -m "Webpack installation and setup"
Из корневой папки:
Кроме того, чтобы подключить его к Webpack, вам необходимо установить так называемый загрузчик ("лодырь" - 😉 ):
В качестве последнего шага, поскольку вы хотите использовать React, вам нужна еще одна конфигурация для преобразования синтаксиса JSX в React в обычный JavaScript.
Из корневой папки:
Теперь, когда все пакеты узлов установлены, вам нужно настроить файлы package.json и webpack.config.js так, чтобы они соответствовали изменениям Babel.
Ниже все добавленное выделил красным.Эти изменения включают в себя все пакеты, которые вы установили.
package.json
webpack.config.js
Вы можете снова запустить приложение. Ничего не должно было измениться, за исключением того, что теперь вы можете использовать будущие функциональные возможности ECMAScript для JavaScript.
Я просто допишу в файл src/index.js, что-то такое, например:
Запускаем проект:
Идем на 8080 порт и в консоли видим:
Создаем файл .babelrc в корне проекта.
Теперь вы можете добавить конфигурацию для Babel, которую вы ранее добавили в свой package.json (в коде файла выше это красным выделил) , в файл .babelrc . Не забудьте удалить конфигурацию из package.json позже.
Babel позволяет вам использовать будущий JavaScript в вашем браузере, потому что он превращает его в ванильный JavaScript. Теперь вы настроены на создание своего первого компонента React.
На этом этапе все файлы проекта доступны в гит-репо react-min-setup-abc
ci -m "Babel installation and setup"
Из корневой папки:
В вашем src / index.js вы можете реализовать свою первую запись в мире React.
src / index.js
Теперь вы должны видеть вывод в своем браузере, а не в консоли разработчика.
Второй параметр - это узел, к которому должен быть добавлен ваш вывод. Помните , когда мы использовали
На этом этапе все файлы проекта доступны в гит-репо react-min-setup-abc
ci -m "React installation and setup"
Из корневой папки:
Вы должны добавить еще несколько настроек в ваш файл конфигурации Webpack.
webpack.config.js
Кроме того, в файле src / index.js вы должны указать , что горячая перезагрузка доступна и должна использоваться.
SRC / index.js
Теперь вы можете запустить свое приложение снова.
Из корневой папки:
Когда вы меняете свой
На этом этапе все файлы проекта доступны в гит-репо react-min-setup-abc ci -m "Installation and setup Hot Module Replacement"
Таким образом, мы выполнили первоначальную настройку самого необходимого для реакт-разработки. Мы создали минимальный установочный пакет, который уже можно дополнять необходимыми модулями и библиотеками, в зависимости от поставленных задач.
Успехов и хорошего кодинга!
Это руководство относится к последним версиям React 16, Webpack 4 и Babel 7.
Facebook создал и поддерживает готовое приложение - creat-react-app, которое уже включает все необходимые настройки и отлично подходит для начинающих разработчиков.
Эта статья больше о том, как научить людей настраивать собственный проект без стороннего шаблонного проекта. В какой-то момент вы начнете использовать инструменты вокруг вашей библиотеки или фреймворка по вашему выбору. В JavaScript вам придется иметь дело с Webpack, Babel и многим другим, и поэтому имеет смысл узнать о них. Я надеюсь, что эта статья поможет вам в этом приключении.
Создание структуры.
Убедитесь, что у вас установлены Node.js и NPM.
node -v
npm -v
Результат:
Если не установлены, то установите с официального сайта.
Я работаю под Windows -8 и в редакторе VS-Code.
Перейдите в нужную вам директорию и создайте основную папку для вашего проекта. У меня это будет папка react-min-setup
mkdir react-min-setup
cd react-min-setup
cd react-min-setup
Выше, я создал папку из КС ( командной строки) и перешел в нее. Теперь у вас есть папка проекта. Далее вы можете инициализировать его как проект npm . Задав ему
-y
сокращенный флаг, вы сообщаете npm, что он должен принимать все значения по умолчанию. Если вы не оставите флажок, вы должны указать информацию о вашем проекте вручную.
npm init -y
Вы можете извлечь файл package.json после инициализации вашего проекта как проекта npm. Он должен быть заполнен вашими значениями по умолчанию. Если вы хотите изменить настройки по умолчанию, вы можете просмотреть и изменить их с помощью следующих команд в командной строке:
npm config list
npm set init.author.name ""
npm set init.author.email "you@example.com"
npm set init.author.url "example.com"
npm set init.license "MIT"
npm set init.author.name "
npm set init.author.email "you@example.com"
npm set init.author.url "example.com"
npm set init.license "MIT"
После настройки вашего проекта npm, вы можете установить пакеты узлов (библиотеки) в свой проект с помощью самого npm. После установки нового пакета узла, он должен появиться в вашем файле package.json .
Я это сделаю из терминала редактора.
В папке проекта я создам папку dist с файлом index.html. В этой папке будут храниться уже готовые для размещения на хостинге, или иного использования, файлы проекта.
index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>React + Webpack 4 + Babel 7 </title> </head> <body> <div id="app"></div> <script src="./bundle.js"></script> </body> </html>
В файле ничего особенного. Есть корневой див, в котором будет размещаться весь React - проект и подключен файл bundle.js из этой же папки dist, в который и будут собираться все файлы нашего проекта, с помощью webpack.
Два важных факта о содержании:
файл bundle.js будет сгенерирован Webpack
Атрибут
id = "app"
поможет нашему корневому компоненту React найти точку входа Поэтому наши следующие возможные шаги:
- настроить Webpack для объединения наших исходных файлов в один файл как bundle.js
- построить наш первый корневой компонент React, который использует точку входа
id = "app"
На этом этапе все файлы проекта доступны в гит-репо react-min-setup-abc ci -m "Initiall commit layout project"
Настройка Webpack
Вы будете использовать Webpack в качестве модуля сборки и инструмента построения приложения. Более того, вы будете использовать webpack-dev-server для обслуживания вашего приложения в локальной среде. В противном случае вы не сможете увидеть его в браузере для его разработки. И последнее, но не менее важное: вам понадобится пакет узла webpack-cli, чтобы позже настроить конфигурацию Webpack в файле конфигурации. Давайте установим все три пакета узлов, используя npm.Из корневой папки:
npm install --save-dev webpack webpack-dev-server webpack-cli
Теперь у вас должна быть папка node_modules, где вы можете найти сторонние зависимости. Зависимости также будут перечислены в файле package.json , так как вы использовали флаг
–save-dev
. Ваша структура папок должна выглядеть следующим образом:
Структура папки:
- dist
- - index.html
- node_modules
- package.json
- - index.html
- node_modules
- package.json
В файле package.json вы можете добавить стартовый скрипт (выделил красным) дополнительно к заданным по умолчанию скриптам для запуска webpack-dev-server.
package.json
"scripts": {
"start": "webpack-dev-server --config ./webpack.config.js --mode development",
"test": "echo \"Error: no test specified\" && exit 1"
},
В файле появились установленные зависимости:
Сценарий определяет, что вы хотите использовать webpack-dev-server с файлом конфигурации с именем webpack.config.js .
--mode development
это Флаг, который просто добавляет WebPack по умолчанию конфигурации , которые пришли с Webpack 4. Вам не нужен флаг для Webpack 3.
Давайте создадим необходимый файл webpack.config.js .
module.exports = { entry: './src/index.js', output: { path: __dirname + '/dist', publicPath: '/', filename: 'bundle.js' }, devServer: { contentBase: './dist' } };
Грубо говоря, в конфигурационном файле сказано, что:
- мы хотим использовать файл src / index.js в качестве точки входа для объединения всех импортированных файлов.
- Связанные файлы приведут к файлу bundle.js, который
- будет сгенерирован в нашей уже настроенной папке / dist . Эта папка будет использоваться для обслуживания нашего приложения.
В нашем проекте отсутствует папка и файл src / index.js . Создадим их. В файл index.js добавим, какой - нибудь вывод в консоль. Например:
console.log('My Minimal React Webpack Babel Setup');
Структура проекта:
- dist
- - index.html
- node_modules
- src
- - index.js
- package.json
- webpack.config.js
- - index.html
- node_modules
- src
- - index.js
- package.json
- webpack.config.js
Теперь вы сможете запустить свой webpack-dev-server.
npm start
По умолчанию, проект запустится на порту 8080. И если посмотрим в консоль, то увидим наше сообщение.
Сейчас, вы подаете свое приложение через Webpack прямо в браузер. Вы связываете файл точки входа src / index.js как bundle.js , используете его в dist / index.html и можете увидеть его console.log()в консоли разработчика.
Пока это только файл src / index.js . Но позже вы импортируете больше файлов JS в этот файл, который автоматически будет упакован Webpack в файл bundle.js, который и будет создан.
На этом этапе все файлы проекта доступны в гит-репо react-min-setup-abc
ci -m "Webpack installation and setup"
Настройка Babel
Babel позволяет вам писать свой код с помощью JavaScript, который еще не поддерживается в большинстве браузеров. Например: JavaScript ES6 (ES2015) и более поздних версиях . С помощью Babel код возвращается обратно в стандартный JavaScript, так что каждый браузер, не имеющий всех реализованных функций JavaScript ES6 и не только, может его интерпретировать. Чтобы заставить Babel работать, вам нужно установить две его основные зависимости.Из корневой папки:
npm install --save-dev @babel/core @babel/preset-env
Кроме того, чтобы подключить его к Webpack, вам необходимо установить так называемый загрузчик ("лодырь" - 😉 ):
npm install --save-dev babel-loader
В качестве последнего шага, поскольку вы хотите использовать React, вам нужна еще одна конфигурация для преобразования синтаксиса JSX в React в обычный JavaScript.
Из корневой папки:
npm install --save-dev @babel/preset-react
Теперь, когда все пакеты узлов установлены, вам нужно настроить файлы package.json и webpack.config.js так, чтобы они соответствовали изменениям Babel.
Ниже все добавленное выделил красным.Эти изменения включают в себя все пакеты, которые вы установили.
package.json
{
"name": "react-min-setup",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"start": "webpack-dev-server --config ./webpack.config.js --mode development",
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "Yaroslav",
"license": "ISC",
"babel": {
"presets": [
"@babel/preset-env",
"@babel/preset-react"
]
},
"devDependencies": {
"@babel/core": "^7.3.3",
"@babel/preset-env": "^7.3.1",
"@babel/preset-react": "^7.0.0",
"babel-loader": "^8.0.5",
"webpack": "^4.29.5",
"webpack-cli": "^3.2.3",
"webpack-dev-server": "^3.2.0"
}
}
webpack.config.js
module.exports = {
entry: './src/index.js',
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
use: ['babel-loader']
}
]
},
resolve: {
extensions: ['*', '.js', '.jsx']
},
output: {
path: __dirname + '/dist',
publicPath: '/',
filename: 'bundle.js'
},
devServer: {
contentBase: './dist'
}
};
Вы можете снова запустить приложение. Ничего не должно было измениться, за исключением того, что теперь вы можете использовать будущие функциональные возможности ECMAScript для JavaScript.
Я просто допишу в файл src/index.js, что-то такое, например:
console.log('My Minimal React Webpack Babel Setup'); const obj={name:'Yaroslav', age: 48, id:1}; let {name} = obj; console.log(name);
Запускаем проект:
npm start
Идем на 8080 порт и в консоли видим:
Необязательный шаг - извлечь конфигурацию Babel в отдельный файл конфигурации .babelrc
Создаем файл .babelrc в корне проекта.
Теперь вы можете добавить конфигурацию для Babel, которую вы ранее добавили в свой package.json (в коде файла выше это красным выделил) , в файл .babelrc . Не забудьте удалить конфигурацию из package.json позже.
Это должно быть настроено только в одном месте!
.babelrc
{ "presets": [ "@babel/preset-env", "@babel/preset-react" ] }
Babel позволяет вам использовать будущий JavaScript в вашем браузере, потому что он превращает его в ванильный JavaScript. Теперь вы настроены на создание своего первого компонента React.
На этом этапе все файлы проекта доступны в гит-репо react-min-setup-abc
ci -m "Babel installation and setup"
Настраиваем React
Чтобы использовать React, вам нужно еще два пакета узлов. Пакеты установим через npm.Из корневой папки:
npm install --save react react-dom
В вашем src / index.js вы можете реализовать свою первую запись в мире React.
src / index.js
import React from 'react'; import ReactDOM from 'react-dom'; const title = 'My Minimal React Webpack Babel Setup'; ReactDOM.render( <div>{title}</div>, document.getElementById('app') );
Теперь вы должны видеть вывод в своем браузере, а не в консоли разработчика.
ReactDOM.render
нужны два параметра. Первый параметр - это ваш JSX
. У него должен быть всегда один корневой узел.
Второй параметр - это узел, к которому должен быть добавлен ваш вывод. Помните , когда мы использовали
<div id="app"></div>
в / index.html файл? Этот же идентификатор - ваша точка входа в React.
На этом этапе все файлы проекта доступны в гит-репо react-min-setup-abc
ci -m "React installation and setup"
Hot Module Replacement
Очень полезный пакет, который позволит вам значительно упростит разработку и сократит время. Когда вы что-то меняете в исходном коде, эти изменения будут применяться в вашем приложении, запущенном в браузере, без перезагрузки всей страницы . Более подробно, на странице приложения - react-hot-loaderИз корневой папки:
npm install --save-dev react-hot-loader
Вы должны добавить еще несколько настроек в ваш файл конфигурации Webpack.
webpack.config.js
const webpack = require('webpack'); module.exports = { entry: './src/index.js', module: { rules: [ { test: /\.(js|jsx)$/, exclude: /node_modules/, use: ['babel-loader'] } ] }, resolve: { extensions: ['*', '.js', '.jsx'] }, output: { path: __dirname + '/dist', publicPath: '/', filename: 'bundle.js' }, plugins: [ new webpack.HotModuleReplacementPlugin() ], devServer: { contentBase: './dist', hot: true } };
Кроме того, в файле src / index.js вы должны указать , что горячая перезагрузка доступна и должна использоваться.
SRC / index.js
import React from 'react'; import ReactDOM from 'react-dom'; const title = 'My Minimal React-16 Webpack- 4 Babel Setup'; ReactDOM.render({title}, document.getElementById('app') ); module.hot.accept();
Теперь вы можете запустить свое приложение снова.
Из корневой папки:
npm start
Когда вы меняете свой
title
в компоненте React в файле src / index.js , вы должны увидеть обновленный вывод в браузере без перезагрузки браузера. Если вы удалите module.hot.accept();
строку в консоли, то браузер выполнил перезагрузку. То есть, если что-то изменилось в коде, изменения применились!
На этом этапе все файлы проекта доступны в гит-репо react-min-setup-abc ci -m "Installation and setup Hot Module Replacement"
Таким образом, мы выполнили первоначальную настройку самого необходимого для реакт-разработки. Мы создали минимальный установочный пакет, который уже можно дополнять необходимыми модулями и библиотеками, в зависимости от поставленных задач.
Успехов и хорошего кодинга!
пятница, 22 февраля 2019 г.
React - Интерактивная таблица. (II).
Это будет вторая часть, посвященная созданию динамической интерактивной таблицы на React.js
В первой части мы сделали динамическую таблицу, в которой мы можем сортировать элементы в столбцах и выводить данные отдельного пользователя на страницу.
В этой части нам нужно добавить клиентскую пагинацию (максимум 50 элементов на странице) добавить фильтрацию - поле поиска элемента по каким-то вводимым символам. Будем показывать отфильтрованные данный из этой таблицы. которые будут соответствовать запросу.
В этом разделе нам нужно предоставить пользователю возможность выбора большого (1000 элементов) или малого (32 элемента) объемов данных для загрузки на страницу с таблицей.
Начнем с конца и предоставим пользователю такое право с помощью двух кнопок, которые будут показываться сразу на экране при загрузке самого приложения, и уже при клике на которые, пользователь может загрузик в таблицу большие (1000 элементов) или малые (32) данные.
На этом этапе код по ссылке: react-table-abc
ci -m "data output from the table row to the page"
Начнем с того, что в нашем стейте компонента
Теперь, для того, чтобы таблицы у нас не рисовались, мы воспользуемся данным флагом и в методе
Создаем компонент
Хорошей практикой считается хранить компоненты в отдельной папке Components, но если их немного, как в этом проекте, то мы можем смело хранить их в src.
В написании этого компонента нет ничего сложного и вы можете написать его по своему усмотрению, или взять готовый код ниже.
Если коротко, то здесь мы создали простой компонент с использованием
Вывели две кнопки, классы для их стилизации, я взял у бутстрапа, и навесили на них событие
Функцию
Для более красивого отображения кнопок по центру, добавили инлайн стили.
Теперь нам нужно подключить вновь созданный компонент в
Подключаем просто:
Передаем в пропсы - еще проше:
Теперь нам нужно написать саму функцию
Как, мы и договорились, функция будет получать
Посмотрим на работу приложения в консоли:
При клике на кнопки, мы получаем разные ссылки по которым и будут подгружаться большие и малые данные для таблицы.
На этом этапе код по ссылке: react-table-abc
ci -m "Creating a component with buttons for links. Stylization, output to the console url - addresses."
Это мы можем сделать в методе
И создадим там же какой-либо метод, куда мы и передадим
Самый простой способ реализовать метод
Изменения стейта оставили без изменений. Все изменения я отметил в коде красным.
Теперь можно посмотреть на приложение в браузере.
При клике будет показываться лоудер и загружаться большая или малая таблица.
На этом этапе код по ссылке: react-table-abc
ci -m "Data output table by clicking on the buttons"
Сейчас он выглядит так:
Мы можем немного изменить названия переменных, для того, чтобы в изменениях стейта у нас остались только флаги, так как их названия будут совпадать.
Теперь мы можем записать установщик новых стейтов в одну строку:
На этом этапе код по ссылке: react-table-abc
ci -m "Refactoring onSort function"
Для создания пагинации мы будем использовать готовый npm-модуль - react-paginate. Вы можете все почитать на странице, а проще сразу посмотреть на демонстрацию его работы. по ссылке со страницы.
Устанавливаем модуль:
Импортируем данный компонент в App:
Сам компонент мы скопируем из этого же кода на странице-демо.
Этот компонент пагинации, нам нужно поставить после таблицы.
Здесь нам нужно задать условие, чтобы пагинация показывалась только когда на странице более 50 элементов.
Количество элементов определим в костанту -
переименуем в скопированном компоненте метод
Этот метод будет вызываться при нажатии на кнопку изменения страницы.
Напишем его в компоненте App и передадим в него некий объект -
При клике на страницу нам приходит объект
Пагинация выглядит очень неважно. Если посмотреть в раздел Elements разработчика, то можно заметить, что её html-структура очень похожа на разметку Bootstrap.
Таким образом мы для стилизации можем просто добавить нужные классы.
На странице компонента мы можем посмотреть те свойства, которые мы можем использовать для стилизации нашего компонента.
Строку
Добавил стили бутстрапа этим свойствам компонента. Отметил красным.
Посмотрим в браузер и увидим, что нужным элементам нашего компонента мы добавили классы бутстрап.
На этом можно закончить стилизацию компонента.
На этом этапе код по ссылке: react-table-abc
ci -m "creation and stylization of pagination."
В теле мы будем изменять номер страницы, поэтому в стейт по умолчанию добавим новый флаг
В теле функции мы будем изменять это поле:
и в стейтах поле
Нам очень важно не изменять поле
Тысяча элементов пусть хранится в стейте, а отображать мы будем только 50.
Для этого мы создадим переменную
Эта константа будет хранить определенную часть данных, которая будет зависеть от номера текущей станицы (
Этот метод принимает первым аргументом массив, а вторым - число элементов под массива (длина под массивов). Более подробно об этом вы можете прочитать в документации Lodash ._chunk.
Здесь мы получаем результирующий массив данных таблиицы:
и нам остается обратиться к его индексу, чтобы забрать нужную часть -
Таким образом мы получим в переменную
Можно посмотреть на приложение в браузере. Мы увидим, что на одну страницу загрузилось ровно 50 элементов.
Теперь при изменении страницы, будет динамически меняться содержимое таблицы.
На этом этапе код по ссылке: react-table-abc
ci -m "Pagination is connected."
Этот параметр позволяет переписывать текущую страницу с родительским свойством. С помщь. него мы синхронизируем номер страницы с состоянием стейта.
Добавим его в самый низ записи компонента:
На этом этапе стоит убедиться. что пагинация работает и ничего не сломалось. Работают фильтры и при загрузке 32 элемента, пагинации нет, а при загрузке 1000 эл. пагинация, фильтрация и вывод отдельного компонента на страницу продолжаю работать.
На этом этапе код по ссылке: react-table-abc
ci m "Synchronize page number with state"
В этом компоненте мы будем использовать React-Hocks, потому что мы хотим взаимодействовать с состоянием компонента не смотря на то, что он "глупый".
Я, в ближайшее время напишу пост по основным хукам Реакт, а пока что приведу компонент полностью и попробую далее объяснить его действие.
Все что возвращает этот компонент, есть ничто иное как обычное поле поиска с кнопкой, которое я взял с сайта Bootstrap Button addons.
Поменял
Импортируем наш новый компонент в App:
Данный компонент нам нужно отрисовать, только тогда, когда у нас загрузились данные. Поэтому, мы разместим компонент поиска над таблицей и все это вместе обернет в компонент реакта, чтобы не добавлять ненужный
В компоненте TableSearch.js cсейчас только метод
Для отступа сверху добавили только
Если посмотреть в браузер, то можно увидеть готовый, но совершенно нерабочий компонент.
На этом этапе код по ссылке: react-table-abc
ci -m "Add layout new component - search field"
Так как нам придется отслеживать наш
И коль скоро, мы используем реакт 16.8, то мы будем использовать хуки.
Импортируем
Добавили метод, который будет отслеживать изменение состояния (импута) -
В теле компонента создадим саму эту функцию, которая будет менять "стейт", точнее нашу переменную
Вот таким образом мы смогли написать изменение стейта в "глупом" компоненте используя реакт-хуки.
Теперь, нам нужно при нажатии на кнопку, передавать состояние данной строки. Для этого кнопке добавим:
И так как мы получаем
В теле компонента App создадим сам метод -
Проверим в консоли, правильно ли мы получаем строку поиска и что она из себя представляет.
Идем в браузер. Вписываем какую-либо строку, например - User, получаем ее в консоли, после нажатия на кнопку поиска.
На этом этапе код по ссылке: react-table-abc
ci -m"We receive data from impu search in the console."
Вначале создадим поле
Теперь в методе
Именно для корректной работы поиска мы создавали параметр
Мы изменяем стейт и реакт будет заходить в метод рендер, после того, как мы будем изменять
Теперь в зависимости от
Для этого в рендере, рядом с этой констатой, мы создадим еще одну:
В нее положим данные, которые мы будем получать, например из
Теперь напишем этот метод в теле компонента App
Здесь мы заберем из стейта два поля деструктуризацией -
Далее, прстая проверка. Если в поле
Если в
Переменная
Теперь мы берем под-поля -
Для корректной работы мы приведем все к нижнему регистру. -
Для проверки на подстроку, мы воспользуемся методом
Если нужна фильтрация, только по определенному полю, то ненужные поля можно просто удалить.
Теперь нам остается поменять
В рендер метод добавим, ниже
Здесь, я думаю, что все понятно. Округляем, потому что может быть дробное число. Делим количество отфильтрованных элементов на кол-во элементов на странице и получаем - кол-во страниц, которые будут показаны для пагинации отфильтрованных элементов.
Таким образом, мы создали таблицу, в которой можно сортировать столбцы, выводить элемент отдельно, фильтровать элементы по поиску, выводить на страницу определенное количество элементов - пагинация. И предоставили пользователю возможность загружать малое и большое кол-во данных.
На этом этапе код по ссылке: react-table-abc
ci -m "add filtering in search"
Да, и если возникли трудности в коде, не знаете где ошибка, то -
Готовое приложение здесь
Первая часть <-
Удачного кодирования!
В первой части мы сделали динамическую таблицу, в которой мы можем сортировать элементы в столбцах и выводить данные отдельного пользователя на страницу.
В этой части нам нужно добавить клиентскую пагинацию (максимум 50 элементов на странице) добавить фильтрацию - поле поиска элемента по каким-то вводимым символам. Будем показывать отфильтрованные данный из этой таблицы. которые будут соответствовать запросу.
В этом разделе нам нужно предоставить пользователю возможность выбора большого (1000 элементов) или малого (32 элемента) объемов данных для загрузки на страницу с таблицей.
Начнем с конца и предоставим пользователю такое право с помощью двух кнопок, которые будут показываться сразу на экране при загрузке самого приложения, и уже при клике на которые, пользователь может загрузик в таблицу большие (1000 элементов) или малые (32) данные.
На этом этапе код по ссылке: react-table-abc
ci -m "data output from the table row to the page"
Выбор данных для загрузки.
В коде, который мы написали в прошлый раз, мы грузим сразу маленький объем данным по ссылке в жизненном цикле компонента асинхронно.(см. код компонентаApp
в componentDidMount()
)
Начнем с того, что в нашем стейте компонента
App
мы добавим новый флаг isModeSelected: false
и изменим значение флага отвечающего за немедленную загрузку данных на страницу isLoading
на false
state ={ isModeSelected: false, isLoading: false, data: [], sort: 'asc', // 'desc' sortField: 'id', row: null, }
Теперь, для того, чтобы таблицы у нас не рисовались, мы воспользуемся данным флагом и в методе
render
проверим. Если мы не выбрали никакой мод, то есть this.state.isModeSelected
мы вырисовываем простой каркас приложения с новым компонентом - ModeSelector
.
if(!this.state.isModeSelected){ return ( <div className="container"> <ModeSelector /> </div> ) }
Создаем компонент
ModeSelector
Как вы догадались, в папке src создадим папку ModeSelector и в ней js-файл с таким же именем.
Хорошей практикой считается хранить компоненты в отдельной папке Components, но если их немного, как в этом проекте, то мы можем смело хранить их в src.
В написании этого компонента нет ничего сложного и вы можете написать его по своему усмотрению, или взять готовый код ниже.
Если коротко, то здесь мы создали простой компонент с использованием
{}
для создания тела функции, потому что в нем мы будем хранить две константы с ссылками на большие и малые данные.
Вывели две кнопки, классы для их стилизации, я взял у бутстрапа, и навесили на них событие
onClick={()=>props.onSelect(smallUrl)}
.
Функцию
onSelect
мы получаем из props
в нее мы передаем константу с url-адресом. Это написание - второй способ передать параметры в функцию. В первой части таблиц, мы использовали метод bind()
, а в этот раз по типу замыкания. Мы передадим сюда функцию в которой обратимся к методу onSelect
из props
и передадим адрес.
import React from 'react'; export default props =>{ const smallUrl = `http://www.filltext.com/?rows=32&id={number|1000}&firstName={firstName}&lastName={lastName}&email={email}&phone={phone|(xxx)xxx-xx-xx}&address={addressObject}&description={lorem|32}`; const bigUrl = `http://www.filltext.com/?rows=1000&id={number|1000}&firstName={firstName}&delay=3&lastName={lastName}&email={email}&phone={phone|(xxx)xxx-xx-xx}&address={addressObject}&description={lorem|32}`; return ( <div style={{display:'flex', justifyContent:'center', padding: '50px 0'}}> <button onClick={()=>props.onSelect(smallUrl)} className="btn btn-success">32 элемента</button> <button onClick={()=>props.onSelect(bigUrl)} className="btn btn-danger">1000 элементов</button> </div> ) }
Для более красивого отображения кнопок по центру, добавили инлайн стили.
Теперь нам нужно подключить вновь созданный компонент в
App
, передать в него название свойства onSelect
и написать сам метод, который будет передаваться как свойство onSelect
, внутри компонента App
.
Подключаем просто:
import ModeSelector from './ModeSelector/ModeSelector';
Передаем в пропсы - еще проше:
if(!this.state.isModeSelected){
return (
<div className="container">
<ModeSelector onSelect={this.modeSelectHandler} />
</div>
)
}
Теперь нам нужно написать саму функцию
modeSelectHandler
в теле компонента:
modeSelectHandler = url => { console.log(url) }
Как, мы и договорились, функция будет получать
url
, который и выведем в консоли.
Посмотрим на работу приложения в консоли:
При клике на кнопки, мы получаем разные ссылки по которым и будут подгружаться большие и малые данные для таблицы.
На этом этапе код по ссылке: react-table-abc
ci -m "Creating a component with buttons for links. Stylization, output to the console url - addresses."
Вывод данных на страницу.
Теперь нам необходимо, после клика скрыть этот элемент и загрузить необходимые данные.Это мы можем сделать в методе
modeSelectHandler
изменив состояние компонента, а именно флаги
isModeSelected
и isLoading
на true
И создадим там же какой-либо метод, куда мы и передадим
url
- this.fetchData(url)
modeSelectHandler = url => { // console.log(url) this.setState({ isModeSelected: true, isLoading: true, }) this.fetchData(url) }
Самый простой способ реализовать метод
fetchData(url)
это переписать под него жизненный цикл компонента componentDidMount()
. Мы просто изменим это название на название метода. Единственное что, так это то, что он будет принимать некий url
, по которому мы должны сделать запрос.
async fetchData(url) { const response = await fetch(url) const data = await response.json() this.setState({ isLoading: false, data: _.orderBy(data, this.state.sortField, this.state.sort) }) }
Изменения стейта оставили без изменений. Все изменения я отметил в коде красным.
Теперь можно посмотреть на приложение в браузере.
При клике будет показываться лоудер и загружаться большая или малая таблица.
На этом этапе код по ссылке: react-table-abc
ci -m "Data output table by clicking on the buttons"
Рефактринг кода
Немного поменяем методonSort
.
Сейчас он выглядит так:
onSort = sortField => { const cloneData = this.state.data.concat(); const sortType = this.state.sort === 'asc' ? 'desc' : 'asc'; const orderedData = _.orderBy(cloneData, sortField, sortType); this.setState({ data: orderedData, sort: sortType, sortField }) }
Мы можем немного изменить названия переменных, для того, чтобы в изменениях стейта у нас остались только флаги, так как их названия будут совпадать.
onSort = sortField => { const cloneData = this.state.data.concat(); const sort = this.state.sort === 'asc' ? 'desc' : 'asc'; const data = _.orderBy(cloneData, sortField, sort); this.setState({ data, sort, sortField }) }
Теперь мы можем записать установщик новых стейтов в одну строку:
onSort = sortField => {
const cloneData = this.state.data.concat();
const sort = this.state.sort === 'asc' ? 'desc' : 'asc';
const data = _.orderBy(cloneData, sortField, sort);
this.setState({ data, sort, sortField})
}
На этом этапе код по ссылке: react-table-abc
ci -m "Refactoring onSort function"
Пагинация
Делать пагинацию самостоятельно с ноля мы не буем, так как есть готовые компоненты, а логика там фиксированная, поэтому мы воспользуемся почти готовым решением.а) Создание компонента пагинации
Можно посмотреть на то, как реализована пагинация в бутстрапе - pagination Bootstrap - здесь есть готовая верстка. Отсюда мы возьмем названия нужных нам классов, в дальнейшем, для некоторой стилизации нашего компонента пагинации.Для создания пагинации мы будем использовать готовый npm-модуль - react-paginate. Вы можете все почитать на странице, а проще сразу посмотреть на демонстрацию его работы. по ссылке со страницы.
Устанавливаем модуль:
npm install react-paginate --save
Импортируем данный компонент в App:
import ReactPaginate from 'react-paginate';
Сам компонент мы скопируем из этого же кода на странице-демо.
<ReactPaginate previousLabel={'previous'} nextLabel={'next'} breakLabel={'...'} breakClassName={'break-me'} pageCount={this.state.pageCount} marginPagesDisplayed={2} pageRangeDisplayed={5} onPageChange={this.handlePageClick} containerClassName={'pagination'} subContainerClassName={'pages pagination'} activeClassName={'active'} />
Этот компонент пагинации, нам нужно поставить после таблицы.
Здесь нам нужно задать условие, чтобы пагинация показывалась только когда на странице более 50 элементов.
Количество элементов определим в костанту -
pageSize
в методе render
this.state.data.length > pageSize
переименуем в скопированном компоненте метод
handlePageClick
в pageChangeHandler
и создадим его в компоненте.
Этот метод будет вызываться при нажатии на кнопку изменения страницы.
pageChangeHandler = page => ( console.log(page) )
Напишем его в компоненте App и передадим в него некий объект -
page
и посмотрим на него в консоли при загрузке 1000 элементов:
При клике на страницу нам приходит объект
selected
с номером страницы. Обраите внимание, что нумерация страниц начинается с ноля. То есть, при клике на 5, в selected
придет -4, при клике на 6 - 5, соответственно.
Пагинация выглядит очень неважно. Если посмотреть в раздел Elements разработчика, то можно заметить, что её html-структура очень похожа на разметку Bootstrap.
Таким образом мы для стилизации можем просто добавить нужные классы.
На странице компонента мы можем посмотреть те свойства, которые мы можем использовать для стилизации нашего компонента.
{ this.state.data.length > pageSize ? <ReactPaginate previousLabel={'<'} nextLabel={'>'} breakLabel={'...'} breakClassName={'break-me'} pageCount={20} marginPagesDisplayed={2} pageRangeDisplayed={5} onPageChange={this.pageChangeHandler} containerClassName={'pagination'} activeClassName={'active'} pageClassName="page-item" pageLinkClassName="page-link" previousClassName="page-item" nextClassName="page-item" previousLinkClassName="page-link" nextLinkClassName="page-link" /> : null }
pageCount={20}
пока что сделали = 20, но потом будем задавать динамически.
Строку
subContainerClassName={'pages pagination'}
убрал полностью. Она нам не нужна.
Добавил стили бутстрапа этим свойствам компонента. Отметил красным.
Посмотрим в браузер и увидим, что нужным элементам нашего компонента мы добавили классы бутстрап.
На этом можно закончить стилизацию компонента.
На этом этапе код по ссылке: react-table-abc
ci -m "creation and stylization of pagination."
б) Связь пагинации с стейтом.
Зная, что номер страницы мы получим в объектеselected
, мы можем получить его сразу методом деструктуризации компонента функции - ({selected})
.
В теле мы будем изменять номер страницы, поэтому в стейт по умолчанию добавим новый флаг
currentPage
с номером - 0
class App extends Component {
state ={
isModeSelected: false,
isLoading: false,
data: [],
sort: 'asc', // 'desc'
sortField: 'id',
row: null,
currentPage: 0,
}
В теле функции мы будем изменять это поле:
pageChangeHandler = ({selected}) => ( this.setState({currentPage: selected}) )
в) Оживляем пагинацию.
Посмотрим на логику отображения таблицы. У нас есть лимит полей для страницы:const pageSize = 50;
и в стейтах поле
data: []
, содержащее все элементы. Поэтому мы в методе render()
создадим отдельную переменную, которую мы будем передавать прямо в таблицу.
Нам очень важно не изменять поле
data
, иначе мы сотрем все данные.
Тысяча элементов пусть хранится в стейте, а отображать мы будем только 50.
Для этого мы создадим переменную
const displayData = _.chunk(filteredData, pageSize)[this.state.currentPage]
Эта константа будет хранить определенную часть данных, которая будет зависеть от номера текущей станицы (
currentPage
из стейта). Здесь мы воспользовались методом _.chunk
библиотеки Lodash.
Этот метод принимает первым аргументом массив, а вторым - число элементов под массива (длина под массивов). Более подробно об этом вы можете прочитать в документации Lodash ._chunk.
Здесь мы получаем результирующий массив данных таблиицы:
_.chunk(filteredData, pageSize)
и нам остается обратиться к его индексу, чтобы забрать нужную часть -
[this.state.currentPage]
Таким образом мы получим в переменную
displayData
нужные данные. И теперь нам остается передать эту переменную в data
таблицы:
{
this.state.isLoading
? <Loader />
: <Table
data={displayData}
onSort={this.onSort}
sort={this.state.sort}
sortField={this.state.sortField}
onRowSelect={this.onRowSelect}
/>
}
Можно посмотреть на приложение в браузере. Мы увидим, что на одну страницу загрузилось ровно 50 элементов.
Теперь при изменении страницы, будет динамически меняться содержимое таблицы.
На этом этапе код по ссылке: react-table-abc
ci -m "Pagination is connected."
г) Синхронизация номера страницы с состоянием нашего стейта.
Это будет необходимо, потому что в будущем это потребуется. Для этого нам нужно воспользоваться свойствомforcePage
со страницы компонента пагинации npm react-paginate.
Этот параметр позволяет переписывать текущую страницу с родительским свойством. С помщь. него мы синхронизируем номер страницы с состоянием стейта.
Добавим его в самый низ записи компонента:
{
this.state.data.length > pageSize
? <ReactPaginate
previousLabel={'<'}
nextLabel={'>'}
breakLabel={'...'}
breakClassName={'break-me'}
pageCount={pageCount}
marginPagesDisplayed={2}
pageRangeDisplayed={5}
onPageChange={this.pageChangeHandler}
containerClassName={'pagination'}
activeClassName={'active'}
pageClassName="page-item"
pageLinkClassName="page-link"
previousClassName="page-item"
nextClassName="page-item"
previousLinkClassName="page-link"
nextLinkClassName="page-link"
forcePage={this.state.currentPage}
/> : null
}
На этом этапе стоит убедиться. что пагинация работает и ничего не сломалось. Работают фильтры и при загрузке 32 элемента, пагинации нет, а при загрузке 1000 эл. пагинация, фильтрация и вывод отдельного компонента на страницу продолжаю работать.
На этом этапе код по ссылке: react-table-abc
ci m "Synchronize page number with state"
Добавляем поиск.
Для этого создадим еще один "глупый" компонент с именем TableSearch. Это подразумеваем создание одноименной папки и файла с расширением.js
в папке src.
В этом компоненте мы будем использовать React-Hocks, потому что мы хотим взаимодействовать с состоянием компонента не смотря на то, что он "глупый".
Я, в ближайшее время напишу пост по основным хукам Реакт, а пока что приведу компонент полностью и попробую далее объяснить его действие.
import React, {useState} from 'react' export default props => { const [value, setValue] = useState('') const valueChangeHandler = event => { setValue(event.target.value) } return ( <div className="input-group mb-3 mt-3"> <div className="input-group-prepend"> <button className="btn btn-outline-secondary" onClick={() => props.onSearch(value)} >Search</button> </div> <input type="text" className="form-control" onChange={valueChangeHandler} value={value} /> </div> ) }
Все что возвращает этот компонент, есть ничто иное как обычное поле поиска с кнопкой, которое я взял с сайта Bootstrap Button addons.
Поменял
class
на className
и добавил закрывающий /
для input
.
Импортируем наш новый компонент в App:
import TableSearch from './TableSearch/TableSearch';
Данный компонент нам нужно отрисовать, только тогда, когда у нас загрузились данные. Поэтому, мы разместим компонент поиска над таблицей и все это вместе обернет в компонент реакта, чтобы не добавлять ненужный
div
.
{ this.state.isLoading ? <Loader /> : <React.Fragment> <TableSearch /> <Table data={displayData} onSort={this.onSort} sort={this.state.sort} sortField={this.state.sortField} onRowSelect={this.onRowSelect} /> </React.Fragment> }
В компоненте TableSearch.js cсейчас только метод
return
import React from 'react'
export default props => {
return (
<div className="input-group mb-3 mt-3">
<div className="input-group-prepend">
<button className="btn btn-outline-secondary" >Search</button>
</div>
<input
type="text"
className="form-control"
/>
</div>
)
}
Для отступа сверху добавили только
mt-3
.
Если посмотреть в браузер, то можно увидеть готовый, но совершенно нерабочий компонент.
На этом этапе код по ссылке: react-table-abc
ci -m "Add layout new component - search field"
Хук заменяющий стейт в реакт
Теперь нам нужно сделать так, чтобы мы что-то писали в поле поиска и после нажатия на кнопку, в наших таблицах происходила фильтрация элементов. То есть так, чтобы только соответствующие поисковому запросу элементы показывались на странице.Так как нам придется отслеживать наш
input
, то нам потребуется стейт.
И коль скоро, мы используем реакт 16.8, то мы будем использовать хуки.
Импортируем
useState
import React, {useState} from 'react' export default props => { const [value, setValue] = useState('') const valueChangeHandler = event => { setValue(event.target.value) } return ( <div className="input-group mb-3 mt-3"> <div className="input-group-prepend"> <button className="btn btn-outline-secondary" onClick={() => props.onSearch(value)} >Search</button> </div> <input type="text" className="form-control" onChange={valueChangeHandler} value={value} /> </div> ) }
value
- это и будет само состояние.
Добавили метод, который будет отслеживать изменение состояния (импута) -
valueChangeHandler
.
В теле компонента создадим саму эту функцию, которая будет менять "стейт", точнее нашу переменную
value
, с помощью setValue
.
Вот таким образом мы смогли написать изменение стейта в "глупом" компоненте используя реакт-хуки.
Теперь, нам нужно при нажатии на кнопку, передавать состояние данной строки. Для этого кнопке добавим:
onClick={() => props.onSearch(value)}
И так как мы получаем
onSearch
с пропертями, то нам этот метод нужно передать в компоненте App.
{
this.state.isLoading
? <Loader />
: <React.Fragment>
<TableSearch onSearch={this.searchHandler} />
<Table
data={displayData}
onSort={this.onSort}
sort={this.state.sort}
sortField={this.state.sortField}
onRowSelect={this.onRowSelect}
/>
</React.Fragment>
}
В теле компонента App создадим сам метод -
searchHandler
searchHandler = search =>( console.log(search) )
Проверим в консоли, правильно ли мы получаем строку поиска и что она из себя представляет.
Идем в браузер. Вписываем какую-либо строку, например - User, получаем ее в консоли, после нажатия на кнопку поиска.
На этом этапе код по ссылке: react-table-abc
ci -m"We receive data from impu search in the console."
Добавляем фильтрацию элементов для поиска.
На данном этапе неважно какие поля нам нужно фильтровать, потому что мы всегда сможем их легко изменить или добавить.Вначале создадим поле
search:''
в стейте компонента App
state ={
isModeSelected: false,
isLoading: false,
data: [],
search: '',
sort: 'asc', // 'desc'
sortField: 'id',
row: null,
currentPage: 0,
}
Теперь в методе
searchHandler
мы будем изменять состояние и сбрасывать текущую страницу, для того, чтобы поиск шел по всему документу корректно. - currentPage: 0
searchHandler = search => { this.setState({search, currentPage: 0}) }
Именно для корректной работы поиска мы создавали параметр
forcePage={this.state.currentPage}
, ранее.
Мы изменяем стейт и реакт будет заходить в метод рендер, после того, как мы будем изменять
search
.
Теперь в зависимости от
search
нам нужно показывать data
. То есть в переменную displayData
положить данные не только по количеству отсортированные, но и отфильтрованные по полю поиска.
Для этого в рендере, рядом с этой констатой, мы создадим еще одну:
const filteredData = this.getFilteredData()
В нее положим данные, которые мы будем получать, например из
getFilteredData()
Теперь напишем этот метод в теле компонента App
getFilteredData(){ const {data, search} = this.state if (!search) { return data } return data.filter(item => { return item['firstName'].toLowerCase().includes(search.toLowerCase()) || item['lastName'].toLowerCase().includes(search.toLowerCase()) || item['email'].toLowerCase().includes(search.toLowerCase()) }) }
Здесь мы заберем из стейта два поля деструктуризацией -
const {data, search} = this.state
Далее, прстая проверка. Если в поле
search
ничего нет, то возвращаем обычные данные - data
Если в
search
что-то есть, то мы будем отфильтровывать данные таблицы.
Переменная
item
попадет в массив, если будет соответствовать условиям фильтрации, иначе мы ее убираем.
Теперь мы берем под-поля -
firstName
, lastName
, email
и проверяем, есть ли там нужная подстрока?
Для корректной работы мы приведем все к нижнему регистру. -
.toLowerCase
Для проверки на подстроку, мы воспользуемся методом
includes()
, который вернет true
если содержится. Иначе false
.
Если нужна фильтрация, только по определенному полю, то ненужные поля можно просто удалить.
Теперь нам остается поменять
pageCount={20}
в ретурне App компонента - ReactPaginate на pageCount={pageCount}
и высчитать его значение динамически:
В рендер метод добавим, ниже
const filteredData = this.getFilteredData()
, потому что кол-во страниц будет зависить от этой константы:
const pageCount = Math.ceil(filteredData.length / pageSize)
Здесь, я думаю, что все понятно. Округляем, потому что может быть дробное число. Делим количество отфильтрованных элементов на кол-во элементов на странице и получаем - кол-во страниц, которые будут показаны для пагинации отфильтрованных элементов.
Таким образом, мы создали таблицу, в которой можно сортировать столбцы, выводить элемент отдельно, фильтровать элементы по поиску, выводить на страницу определенное количество элементов - пагинация. И предоставили пользователю возможность загружать малое и большое кол-во данных.
На этом этапе код по ссылке: react-table-abc
ci -m "add filtering in search"
Да, и если возникли трудности в коде, не знаете где ошибка, то -
debager
пишем в коде, и далее, в хроме дебажим все по шагам.
Готовое приложение здесь
Первая часть <-
Хотите освоить самые современные методы написания React приложений? Надоели простые проекты? Нужны курсы, книги, руководства, индивидуальные занятия по React и не только? Хотите стать разработчиком полного цикла, освоить стек MERN, или вы только начинаете свой путь в программировании, и не знаете с чего начать, то пишите через форму связи, подписывайтесь на мой канал в Телеге, вступайте в группу на Facebook.
Удачного кодирования!
Хотите освоить самые современные методы написания React приложений? Надоели простые проекты? Нужны курсы, книги, руководства, индивидуальные занятия по React и не только? Хотите стать разработчиком полного цикла, освоить стек MERN, или вы только начинаете свой путь в программировании, и не знаете с чего начать, то пишите через форму связи, подписывайтесь на мой канал в Телеге, вступайте в группу на Facebook.Пишите мне - kolesnikovy70 почта gmail.com