Статьи

Обработка событий в React

В пост- рендеринге сервиса RESTful с React мы создали простой пользовательский интерфейс, который отображает список сотрудников, извлеченный из сервиса RESTful. В рамках этого поста мы расширим то же приложение для поддержки операций добавления и удаления сотрудников.

Мы начнем с обновления бэкэнд интерфейса реагирующего приложения с операцией добавления / удаления сотрудников, а также с изменения существующего метода get employee для возврата списка сотрудников, выполнив следующие действия:

Шаг 1. Определите метод addEmployee, помеченный @PostMapping («/ employee / add»), который будет добавлять сотрудника в список сотрудников на уровне класса:

1
2
3
4
5
6
7
@PostMapping("/employee/add")
public List<Employee> addEmployee(final @RequestBody Employee employee) {
    System.out.println("Adding employee with name : " + employee.getName());
    if(employee.getName() != null && employee.getName().length() > 0)
              employeeList.add(new Employee(employeeList.size(), employee.getName(), "IT"));
    return employeeList;
}

Шаг 2. Определите метод deleteEmployee, помеченный @PostMapping («/ employee / delete»), который будет удалять сотрудника из списка сотрудников уровня класса, соответствующего имени сотрудника, следующим образом:

1
2
3
4
5
6
7
8
9
@PostMapping("/employee/delete")
public List<Employee> deleteEmployee(final @RequestBody Employee employee) {
    System.out.println("Deleting employee with name : " + employee.getName());
    final Optional<Employee> optional = employeeList.stream().filter(e -> e.getName().equalsIgnoreCase(employee.getName())).findAny();
     if(optional.isPresent()){
        employeeList.remove(optional.get());
     }
    return employeeList;
}

В конечном итоге ReactAppApplication.java должен выглядеть следующим образом:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
@SpringBootApplication
@RestController
public class ReactAppApplication {
 
    final List<Employee> employeeList = new ArrayList<>();
     
    public static void main(String[] args) {
        SpringApplication.run(ReactAppApplication.class, args);
    }
 
    @GetMapping("/employee/get")
    public List<Employee> get() {
        return employeeList;
    }
     
    @PostMapping("/employee/add")
    public List<Employee> add(final @RequestBody Employee employee) {
        System.out.println("Adding employee with name : " + employee.getName());
        if(employee.getName() != null && employee.getName().length() > 0)
         employeeList.add(new Employee(employeeList.size(), employee.getName(), "IT"));
        return employeeList;
    }
     
    @PostMapping("/employee/delete")
    public List<Employee> delete(final @RequestBody Employee employee) {
        System.out.println("Deleting employee with name : " + employee.getName());
        final Optional<Employee> optional = employeeList.stream().filter(e -> e.getName().equalsIgnoreCase(employee.getName())).findAny();
        if(optional.isPresent()){
            employeeList.remove(optional.get());
        }
        return employeeList;
    }
}

Шаг 3: Определите метод / обработчик addEmployee в компоненте ReactApp, который выполняет вызов POST с именем сотрудника в качестве полезной нагрузки для метода addEmployee, который мы только что определили в нашем контроллере, следующим образом:

/Users/ArpitAggarwal/react-app/app/components/react-app.jsx

01
02
03
04
05
06
07
08
09
10
11
12
13
14
addEmployee(employeeName){
 
        let _this = this;
        this.Axios.post('/add', {
            name: employeeName
         })
          .then(function (response) {
            console.log(response);
            _this.setState({employees: response.data});
          })
          .catch(function (error) {
            console.log(error);
          });
}

Шаг 4: Привязать обработчик addEmployee в конструкторе компонента ReactApp :

1
2
3
4
5
6
7
8
9
constructor(props) {
        super(props);
        this.state = {employees: []};
        this.addEmployee = this.addEmployee.bind(this);
        this.Axios = axios.create({
            baseURL: "/employee",
            headers: {'content-type': 'application/json', 'creds':'user'}
        });
}

Шаг 5. Рендеринг дочернего компонента — AddEmployee как часть метода рендеринга компонента ReactApp , передавая обработчик addEmployee в качестве реагирующих действий для установления родительского дочернего взаимодействия:

1
2
3
4
5
6
7
8
render() {
        return (
                <div>
                  <AddEmployee addEmployee={this.addEmployee}/>
                  <EmployeeList employees={this.state.employees}/>
                </div>
        )
}

Шаг 6: Создайте компонент add-employee внутри каталога компонентов следующим образом:

1
2
cd react-app/app/components/
touch add-employee.jsx

И скопируйте следующий контент:

реагировать-приложение / приложения / компоненты / дополнения employee.jsx

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
import React, { Component, PropTypes } from 'react'
 
export default class AddEmployee extends React.Component {
 
  render(){
    return (
       <div>
          <input type = 'text' ref = 'input' />
          <button onClick = {(e) => this.handleClick(e)}>
             Add Employee
          </button>
       </div>
    )
  }
  handleClick(e) {
     const node = this.refs.input
     const text = node.value.trim()
     console.log(text);
     this.props.addEmployee(text)
     node.value = ''
  }
}

Определенная выше функция handleClick (e) вызывается при нажатии кнопки «Добавить сотрудника», которая дополнительно вызывает обработчик addEmployee, определенный в ReactApp, с использованием реквизита .

Имея все это в наличии, наше реагирующее приложение может выполнять операции добавления сотрудников. Далее мы расширим то же самое для поддержки операции удаления сотрудника, выполнив следующие шаги

Шаг 7: Определите обработчик deleteEmployee и привяжите его в ReactApp так же, как мы делали для обработчика addEmployee :

/Users/ArpitAggarwal/react-app/app/components/react-app.jsx

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
constructor(props) {
        super(props);
        this.state = {employees: []};
        this.addEmployee = this.addEmployee.bind(this);
        this.deleteEmployee = this.deleteEmployee.bind(this);
        this.Axios = axios.create({
            baseURL: "/employee",
            headers: {'content-type': 'application/json', 'creds':'user'}
        });
}
 
deleteEmployee(employeeName){
        let _this = this;
        this.Axios.post('/delete', {
            name: employeeName
          })
          .then(function (response) {
            _this.setState({employees: response.data});
            console.log(response);
          })
          .catch(function (error) {
            console.log(error);
          });
}

Шаг 8: Передайте обработчик deleteEmployee компоненту EmployeeList, который затем передаст его дочернему контейнеру:

1
2
3
4
5
6
7
8
render() {
        return (
                <div>
                  <AddEmployee addEmployee={this.addEmployee}/>
                  <EmployeeList employees={this.state.employees} deleteEmployee={this.deleteEmployee}/>
                </div>
            )
    }

В конце концов, компонент ReactApp должен выглядеть следующим образом:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
'use strict';
const React = require('react');
var axios = require('axios');
 
import EmployeeList from './employee-list.jsx'
import AddEmployee from './add-employee.jsx'
 
export default class ReactApp extends React.Component {
 
    constructor(props) {
        super(props);
        this.state = {employees: []};
        this.addEmployee = this.addEmployee.bind(this);
        this.deleteEmployee = this.deleteEmployee.bind(this);
        this.Axios = axios.create({
            baseURL: "/employee",
            headers: {'content-type': 'application/json', 'creds':'user'}
        });
    }
 
    componentDidMount() {
        let _this = this;
        this.Axios.get('/get')
          .then(function (response) {
             console.log(response);
            _this.setState({employees: response.data});
          })
          .catch(function (error) {
            console.log(error);
          });
    }
     
    addEmployee(employeeName){
 
        let _this = this;
        this.Axios.post('/add', {
            name: employeeName
         })
          .then(function (response) {
            console.log(response);
            _this.setState({employees: response.data});
          })
          .catch(function (error) {
            console.log(error);
          });
    }
     
    deleteEmployee(employeeName){
        let _this = this;
        this.Axios.post('/delete', {
            name: employeeName
          })
          .then(function (response) {
            _this.setState({employees: response.data});
            console.log(response);
          })
          .catch(function (error) {
            console.log(error);
          });
    }
    render() {
        return (
                <div>
                  <AddEmployee addEmployee={this.addEmployee}/>
                  <EmployeeList employees={this.state.employees} deleteEmployee={this.deleteEmployee}/>
                </div>
            )
    }
}

Шаг 9: Обновите компонент EmployeeList, чтобы передать обработчик deleteEmployee своему дочернему компоненту — Employee , импортировав его вместе с изменением в методе render, чтобы получить столбец Delete:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
const React = require('react');
import Employee from './employee.jsx'
 
export default class EmployeeList extends React.Component{
     
    render() {
        var employees = this.props.employees.map((employee, i) =>
            <Employee key={i} employee={employee} deleteEmployee={() => this.props.deleteEmployee(employee.name)}/>
        );
         
        return (
            <table>
                <tbody>
                    <tr>
                        <th>ID</th>
                        <th>Name</th>
                        <th>Department</th>
                        <th>Delete</th>
                    </tr>
                    {employees}
                </tbody>
            </table>
        )
    }
}

Шаг 10: Обновите компонент Employee для рендеринга — компонент DeleteEmployee, передавший обработчик deleteEmployee :

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
const React = require('react');
import DeleteEmployee from './delete-employee.jsx'
 
export default class Employee extends React.Component{
    render() {
        return (
            <tr>
                <td>{this.props.employee.id}</td>
                <td>{this.props.employee.name}</td>
                <td>{this.props.employee.department}</td>
                <td><DeleteEmployee deleteEmployee={this.props.deleteEmployee}/></td>
            </tr>
        )
    }
}

Шаг 11: Создайте компонент delete-employee внутри каталога компонентов:

1
2
cd react-app/app/components/
touch delete-employee.jsx

И скопируйте следующий контент:

реагировать-приложение / приложения / компоненты / удаление-employee.jsx

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
import React, { Component, PropTypes } from 'react'
 
export default class DeleteEmployee extends React.Component {
  render(){
    return (
          <button onClick = {(employeeName) => this.handleDelete(employeeName)}>
             Delete
          </button>
    )
 
}
  handleDelete(employeeName) {
   this.props.deleteEmployee(employeeName);
  }
}

Определенная выше функция handleDelete (employeeName) вызывается при нажатии кнопки «Удалить», что дополнительно вызывает обработчик deleteEmployee, определенный в ReactApp, с использованием реквизита .

Со всеми на месте структура каталогов должна выглядеть так:

Теперь перезапустите приложение и посетите http: // localhost: 8080 , оно должно выглядеть так, как показано на скриншоте ниже, как только вы добавите несколько сотрудников.

Полный исходный код размещен на github .