Skip to content

Commit ba0364d

Browse files
authored
Merge pull request #16 from maxchistt/WebSocket
Web socket
2 parents 720f7fe + dea0374 commit ba0364d

File tree

15 files changed

+296
-84
lines changed

15 files changed

+296
-84
lines changed

client/package-lock.json

Lines changed: 5 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

client/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
"react-scripts": "4.0.3",
1717
"react-stack-grid": "^0.7.1",
1818
"react-textarea-autosize": "^8.3.3",
19+
"react-use-websocket": "^2.7.1",
1920
"remark-gfm": "^1.0.0",
2021
"web-vitals": "^0.2.4",
2122
"workbox-background-sync": "^5.1.4",

client/src/Hooks/useDebouncedEffect.hook.js

Lines changed: 0 additions & 37 deletions
This file was deleted.
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
/** @file useDebouncedFunction.hook.js */
2+
import { useEffect, useReducer } from 'react';
3+
4+
/**
5+
* Хук Debounced Function
6+
* @param {(arg)=>void} callback
7+
* @param {number} delayms
8+
*/
9+
function useDebouncedFunction(callback, delayms) {
10+
const [state, debounced] = useReducer((state, arg) => {
11+
return { count: state.count + 1, arg: arg }
12+
}, { count: 0, arg: undefined })
13+
useEffect(() => {
14+
const handler = setTimeout(() => {
15+
if (state.count) callback(state.arg)
16+
}, delayms)
17+
return () => clearTimeout(handler)
18+
// eslint-disable-next-line react-hooks/exhaustive-deps
19+
}, [state])
20+
return debounced
21+
}
22+
23+
export default useDebouncedFunction
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
/**@file useUpdaterSocket.hook.js */
2+
import { useCallback } from "react"
3+
import useWebSocket from 'react-use-websocket'
4+
import useDebouncedFunction from "./useDebouncedFunction.hook"
5+
import { useHttp } from "./http.hook"
6+
7+
const WS_PORT = process.env.WS_PORT || 3030
8+
9+
/**
10+
* Хук веб-сокета обновления данных
11+
* @param {void} updateData
12+
* @param {*} auth
13+
*/
14+
function useUpdaterSocket(updateData, auth) {
15+
const { request } = useHttp()
16+
17+
/**дебонсированный обработчик входящего обновления */
18+
const debouncedUpdate = useDebouncedFunction(updateData, 200)
19+
20+
/**колбек для получения url сокета */
21+
const getSocketUrl = useCallback(async () => {
22+
return new Promise(resolve => {
23+
request("/getIp")
24+
.then((data) => {
25+
const ip = data.ip
26+
const socketAddress = "ws://" + (ip || "localhost") + ":" + WS_PORT
27+
console.log("socketAddress", socketAddress)
28+
resolve(socketAddress)
29+
})
30+
.catch((err) => console.log(err))
31+
})
32+
// eslint-disable-next-line react-hooks/exhaustive-deps
33+
}, [])
34+
35+
/**опции обработки событий сокета */
36+
const socketOptions = {
37+
onOpen: (e) => {
38+
sendRegisterMsg()
39+
console.log("ws open")
40+
},
41+
onClose: (e) => {
42+
console.error("ws close")
43+
},
44+
onMessage: (e) => {
45+
console.log("ws update message")
46+
debouncedUpdate()
47+
},
48+
onError: (e) => {
49+
console.error("ws error", e)
50+
},
51+
}
52+
53+
/**подключение WebSocket */
54+
const { sendMessage } = useWebSocket(getSocketUrl, socketOptions)
55+
56+
/**дебонсированный обработчик отсылаемого обновления */
57+
const sendUpdateMsgDebounced = useDebouncedFunction(sendUpdateMsg, 200)
58+
59+
/** отпрака сообщения сокета */
60+
function sendMsg(target) {
61+
const msg = JSON.stringify({
62+
userId: auth.userId,
63+
target
64+
})
65+
sendMessage(msg)
66+
}
67+
68+
/**отправка отсылаемого обновления */
69+
function sendUpdateMsg() {
70+
sendMsg("update")
71+
}
72+
73+
/**отпрака сообщения регистрации сокета */
74+
function sendRegisterMsg() {
75+
sendMsg("register")
76+
}
77+
78+
return [sendUpdateMsgDebounced]
79+
}
80+
81+
export default useUpdaterSocket

client/src/NoteComponents/ModalNoteEdit.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,10 @@ function calcMaxRows() {
2525
*/
2626
function ModalNoteEdit() {
2727
/**получение контекста */
28-
const { removeNote, changeNoteColor, unsetEditNoteId, editNoteContent, getNoteByIndex, editNoteId } = React.useContext(NotesContext)
28+
const { removeNote, changeNoteColor, unsetEditNoteId, editNoteContent, getNoteById, editNoteId } = React.useContext(NotesContext)
2929

3030
/** обьект заметки */
31-
const note = getNoteByIndex(editNoteId)
31+
const note = getNoteById(editNoteId)
3232
React.useEffect(() => { if (note !== null) open() }, [note])
3333

3434
/**хук состояния формы */

client/src/NoteComponents/NoteItem.js

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
* @file NoteItem.js
33
*/
44
import React, { useContext } from 'react'
5-
import PropTypes from 'prop-types'
65
import NotesContext from '../Context/NotesContext'
76
import Note, { PropTypeNote } from '../Shared/noteType/Note'
87
import ReactMarkdown from 'react-markdown'
@@ -18,7 +17,7 @@ function fixLineBreaks(mdStr) {
1817
* @param {*} param0
1918
*
2019
*/
21-
function NoteItem({ note = new Note(), index }) {
20+
function NoteItem({ note = new Note() }) {
2221
/**Подключение контекста */
2322
const { setEditNoteId, editNoteOrder } = useContext(NotesContext)
2423

@@ -39,7 +38,7 @@ function NoteItem({ note = new Note(), index }) {
3938
<div className="p-1" >
4039
<div className="card" style={{ backgroundColor: bgColor }} >
4140
{/**Заголовок и текст заметки с обработчиками отображения markdown*/}
42-
<div className="card-body" onClick={() => setEditNoteId(index)} >
41+
<div className="card-body" onClick={() => setEditNoteId(note.id)} >
4342
<div
4443
className="card-title h5"
4544
style={{ overflow: "hidden", display: "-webkit-box", WebkitLineClamp: String(lineClip / 2), WebkitBoxOrient: "vertical" }} >
@@ -56,14 +55,14 @@ function NoteItem({ note = new Note(), index }) {
5655
<button
5756
className={footerBtn.className}
5857
style={footerBtn.style}
59-
onClick={() => editNoteOrder(index, false)}
58+
onClick={() => editNoteOrder(note.id, false)}
6059
>
6160
<i className="bi bi-chevron-compact-right"></i>
6261
</button>
6362
<button
6463
className={footerBtn.className}
6564
style={footerBtn.style}
66-
onClick={() => editNoteOrder(index, true)}
65+
onClick={() => editNoteOrder(note.id, true)}
6766
>
6867
<i className="bi bi-chevron-compact-left"></i>
6968
</button>
@@ -75,8 +74,7 @@ function NoteItem({ note = new Note(), index }) {
7574

7675
// Валидация
7776
NoteItem.propTypes = {
78-
note: PropTypeNote.isRequired,
79-
index: PropTypes.number
77+
note: PropTypeNote.isRequired
8078
}
8179

8280
export default NoteItem

client/src/NoteComponents/NoteList.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,9 +54,9 @@ function NoteList(props) {
5454
{/**Отзывчивая сетка карточек */}
5555
<StackGrid className="container p-0" {...gridSettings}>
5656
{/**Рендер каждой карточки из массива */}
57-
{Array.isArray(props.notes) ? (props.notes.sort(sortByOrder).reverse().map((note, index) => {
57+
{Array.isArray(props.notes) ? (props.notes.sort(sortByOrder).reverse().map((note) => {
5858
return (
59-
<NoteItem note={note} key={note.id} index={index} />
59+
<NoteItem note={note} key={note.id} />
6060
)
6161
})) : null}
6262
</StackGrid>

0 commit comments

Comments
 (0)