Не рендерится полученая data, который получил из socket.io | ReactJS / NodeJS
Есть приложение, клиент на React, а сервер на node js. Ситуация такая: Я получаю данные с mysql (файл: matches.js) и передаю их на клиент с помощью socket-io. Со стороны клиента пишу конфиг socket.io-client(файл: HotBoard.jsx). Но рендер (табличка с live матчами) не отображается. Подскажите и объясние что же не так?
Так же приветствуется критика по коду, желательно чтобы был некий рефакторинг. Нужно socket io в node, был в отдельном файле, т.к в дальнейшем много чего будет отправлятся по сокету.
Ниже указал исходники файлов:
- app.js (main),
- matches.js (контроллер),
- matches.js (роутер),
- HotBoard.jsx (client React)
app.js (входной файл):
require('dotenv').config();
const express = require('express');
const PORT = process.env.PORT || 8080;
const axios = require('axios');
const bodyParser = require('body-parser');
const cors = require('cors');
const matchesRoutes = require('./routes/matches.js');
const app = express();
const server = app.listen(PORT, (err) => {
if(err) return err;
console.log(`Server on ${PORT} is running...`);
});
app.use(bodyParser.urlencoded({extended: true}));
app.use(cors());
app.use(express.json());
app.use('/matches', matchesRoutes);
module.exports = app;
matches.js (./controller):
const db = require('../db.js');
const app = require('../app');
const http = require('http');
const server = http.createServer(app);
const socketIO = require('socket.io')(server, {
cors: {
origin: 'http://localhost:3000'
}
})
module.exports.live = (req, res) => {
db.query('SELECT * FROM livematches', ((err, result) => {
if(err) throw err;
socketIO.emit('livematches', result);
// res.send(result);
}));
}
server.listen(8081, () => {
console.log('Socket.io listening on 8081');
});
Хотел сделать на одном порту, как и в основном - входном файле app.js (:8080), но не получалось, да и в статьях прочитал, что сокеты нужно использовать на другом порте.
matches.js (./routes):
const express = require('express');
const router = express.Router();
const controller = require('../controllers/matches.js');
router.get('/live', controller.live);
module.exports = router;
HotBoard.jsx:
import React, { useEffect, useState } from 'react';
import './HotBoard.css';
import { Swiper, SwiperSlide } from "swiper/react";
import SwiperCore, { Autoplay } from 'swiper';
import axios from 'axios';
import Tippy from '@tippyjs/react';
import 'tippy.js/dist/tippy.css';
import friendly from '../../assets/ico/friendly.webp';
import notRecogLeague from '../../assets/ico/notRecogLeague.webp';
import undefTeam from '../../assets/ico/undefTeam.webp';
import wcLogo from '../../assets/ico/wcLogo.webp';
import io from 'socket.io-client';
SwiperCore.use([Autoplay]);
const socket = io('http://localhost:8081');
function HotBoard() {
const[liveMatches, setLiveMatches] = useState();
const[matchesQuant, setMatchesQuant] = useState('0');
useEffect(() => {
const fetchData = async () => {
socket.on('livematches', data => {
setLiveMatches(data && data.map((e, i) => {
return <SwiperSlide key={'live' + i}>
<div className='slideWrap'>
<progress value={e.time.includes('Доп.') ? String(e.time).split('. ')[1].replace('\'', '') : String(e.time).replace('\'', '') && e.time === 'Перерыв' ? '45' : String(e.time).replace('\'', '')} max={e.time.includes('Доп.') ? '120' : '90'}></progress>
<span className="hName">{e.hName.slice(0, 10)}</span>
<Tippy placement='bottom' content={e.hName}>
<img width={'13px'} src={e.hLogo === null ? undefTeam : e.hLogo} alt={e.hName} />
</Tippy>
<span className='hScore'>{e.hScore}</span>
<div className="lLogoTime">
<Tippy placement='bottom' content={e.lName + ' | ' + String(e.round).replace('null', '') + ', ' + String(e.roundInfo).replace('null', '')}>
<img width={'14px'} src={e.lLogo === 'https://s.scr365.net/s1/logo/13_36_14/fPHr8_16_439.png' ? friendly : e.lLogo && e.lLogo === 'https://s.scr365.net/img/ball16.png' ? notRecogLeague : e.lLogo && e.lLogo === 'https://s.scr365.net/s1/logo/12_250_17/a7wHB_16_438.png' ? friendly : e.lLogo && e.lLogo === 'https://s.scr365.net/s1/logo/22_33_11/46atU_16_742.png' ? wcLogo : e.lLogo} alt={e.lName} />
</Tippy>
<span className="time">{e.time === 'Перерыв' ? 'Пер.' : e.time && e.time.includes('Доп.') ? `${'ДВ' + e.time.split('.')[1]}` : e.time}</span>
</div>
<span className='aScore'>{e.aScore}</span>
<Tippy placement='bottom' content={e.aName}>
<img width={'13px'} src={e.aLogo === null ? undefTeam : e.aLogo} alt={e.aName} />
</Tippy>
<span className="aName">{e.aName.slice(0, 10)}</span>
</div>
</SwiperSlide>
}));
setMatchesQuant(data.length);
if(data.length > 0) document.querySelector('.hotBoard .liveWrap span').style.color = 'red';
});
}
fetchData();
}, []);
return (
<div className="hotBoard">
<Swiper centeredSlides={true} grabCursor={true} speed={5000} autoplay={{delay: 1, disableOnInteraction: false}} slidesPerView={2} breakpoints={{280: {slidesPerView: 1}, 540: {slidesPerView: 2}, 768: {slidesPerView: 3}, 1200: {slidesPerView: 5}, 1920: {slidesPerView: 6}}} freeMode={true}>
{liveMatches}
</Swiper>
<div className="liveWrap">
<Tippy placement='bottom' content='Количество матчей'>
<span>{matchesQuant}</span>
</Tippy>
</div>
</div>
);
}
export default HotBoard;