как использовать React Hooks для использования сервиса Spring WebFlux - PullRequest
0 голосов
/ 21 мая 2019

Я понимаю / считаю, что я должен отдавать предпочтение функциональным компонентам вместо компонентов класса, чтобы применять изоляцию ответственности.С появлением React Hooks появился новый подход, позволяющий избежать использования Class и при этом сохранять состояние функции.

Я создаю очень простую службу отдыха Web Flux.Я создал очень простую страницу React, используя Hooks и Axon, и получаю «data.map не является функцией RestApiHooksComponent».Если я попробую этот же код, использующий типичную службу отдыха, он будет работать должным образом (под типичной услугой отдыха я подразумеваю синхронный код без каких-либо реактивных функций).

Я полагаю, что мне не хватает какой-то базовой идеи, когда происходит реакцияВеб-поток.Есть несколько примеров, показывающих, как использовать Webflux от React, но никто не показывает, как использовать Hooks (по крайней мере, я не нашел его).Разве Хукс не соответствует Reactive paradigma?Основываясь на моих ограниченных знаниях React, я думаю, что это будет хорошее совпадение: обычный пользовательский случай потребляет список из сервиса, который приходит в поток, и показывает его как доступный.

Front End

package.json

...
  "dependencies": {
    "axios": "^0.18.0",
    "react": "^16.8.6",
    "react-dom": "^16.8.6",
    "react-scripts": "3.0.1"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  }
...

App.js

import React, { useEffect, useState } from "react";
import axios from "axios";

export default function RestApiHooksComponent() {
  const [data, setData] = useState([]);

  useEffect(() => {
    axios
      .get("http://127.0.0.1:8080")
      .then(result => setData(result.data));
  }, []);

  return (
    <div>
      <ul>
        {data.map(item => (
          <li key={item.result}>
            {item.result}: {item.result}
          </li>
        ))}
      </ul>
    </div>
  );
}

index.js

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';


ReactDOM.render(<App />, document.getElementById('root'));

LoanTable.js

import React from 'react'

const LoanTable = props => (
    <table>
        <thead>
            <tr>
                <th>Result</th>
            </tr>
        </thead>
        <tbody>
            {props.loans.length > 0 ? (
                props.loans.map(loan => (
                    <tr>
                        <td>{loan.result}</td>

                    </tr>
                ))
            ) : (
                    <tr>
                        <td>No loans</td>
                    </tr>
                )}
        </tbody>
    </table>
)

export default LoanTable

Служба Webflux Rest

Контроллер:

@RestController
public class LoansController {
    @Autowired
    private LoansService loansService;

    @CrossOrigin
    @RequestMapping(method = RequestMethod.GET, produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    @ResponseBody
    public Flux<Loans> findAll() {
        Flux<Loans> loans = loansService.findAll();
        return loans;
    }
}

Служба:

@Service
public class LoansService implements ILoansService {

    @Autowired
    private LoansRepository loansRepository;
    @Override
    public Flux<Loans> findAll() {

        return loansRepository.findAll();
    }
}

Webflux config

@Configuration
@EnableWebFlux
public class WebFluxConfig implements WebFluxConfigurer
{  
}

НЕ МНОГО СООТВЕТСТВУЮЩИХ ДЕТАЛЕЙ, НО Я ДОБАВЛЕН, ЧТОБЫ ПОКАЗАТЬ, ЭТО ПОЛНОСТЬЮ НОБЛОКИРУЮЩИЙ КОД:

MongoDb config

@Configuration
@EnableReactiveMongoRepositories(basePackages = "com.mybank.web.repository")
public class MongoConfig extends AbstractReactiveMongoConfiguration
{  
    @Value("${port}")
    private String port;

    @Value("${dbname}")
    private String dbName;

    @Override
    public MongoClient reactiveMongoClient() {
        return MongoClients.create();
    }

    @Override
    protected String getDatabaseName() {
        return dbName;
    }

    @Bean
    public ReactiveMongoTemplate reactiveMongoTemplate() {
        return new ReactiveMongoTemplate(reactiveMongoClient(), getDatabaseName());
    }
}

Pom:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.4.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.mybank</groupId>
    <artifactId>web</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>web</name>
    <description>webflux</description>

    <properties>
        <java.version>11</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-mongodb-reactive</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-webflux</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>io.projectreactor</groupId>
            <artifactId>reactor-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

***отредактированный

вывод службы веб-потока

data:{"timestamp":1558126555269,"result":"8"} data:{"timestamp":1558132444247,"result":"10"} data:{"timestamp":1558132477916,"result":"10"} data:{"timestamp":1558132596327,"result":"14"}

1 Ответ

1 голос
/ 21 мая 2019

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

useEffect(() => {
    axios
      .get("http://127.0.0.1:8080")
      .then(result => {
          const items = result.data // It should be an array to map
          console.log(items)
          if (items && items.length) {
             setData(items)
          }
       });
  }, []);
...