ソケット学習
10037 ワード
SOcketのみを使用するサイト
https://www.youtube.com/watch?v=CgV8omlWq2o&t=29s
https://github.com/NikValdez/ChatAppTut
https://hoony-gunputer.tistory.com/entry/socket-io%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0
現代JavaScript WebSocket
https://poiemaweb.com/nodejs-socketio
ソケット接続に失敗した場合
https://velog.io/@jun17114/nodeJS%EC%99%80-React-Socket.io%EB%A1%9C-%ED%86%B5%EC%8B%A0
https://poiemaweb.com/nodejs-socketio
ソケット接続に失敗した場合
https://velog.io/@jun17114/nodeJS%EC%99%80-React-Socket.io%EB%A1%9C-%ED%86%B5%EC%8B%A0
初めてやった.
```bash
# npm으로 패키지를 설치할 때는 아래 명령어를 사용해요!
# 옵션은 필요한 경우에만 적어줍니다.
# npm install [옵션] [설치할 패키지 이름]
npm install -g yarn
# 이 명령어는 "npm으로 yarn을 컴퓨터 전체에 설치한다"는 뜻입니다.
# -g 옵션은 컴퓨터 전체에서 쓸 수 있게 한다는 뜻입니다.
```
```bash
yarn add [옵션] [설치할 패키지 이름]
```
CRA(create-act-app)で始まる応答
CRAをガーゼで取り付けましょう!
# 옵션 global은 전역에 이 패키지를 깔겠다는 뜻입니다.
yarn add global create-react-app
```bash
# yarn create react-app [우리의 첫 리액트 프로젝트 이름]
# 우리가 설치한 create-react-app 패키지를 써서 프로젝트를 만들어요.
# 주의! 꼭 sparta_react 폴더 경로에서 입력해주세요!
yarn create react-app week-1
```
npm i quillvscコード=>応答スキャン=>es 7=>vscコード上でrfc自動完了
delta
*client
import React, {useCallback, useEffect, useState} from 'react'
import Quill from "quill"
import "quill/dist/quill.snow.css"
import {io} from 'socket.io-client'
const TOOLBAR_OPTIONS = [
[{header: [1, 2, 3, 4, 5, 6, false]}],
[{font: []}],
[{list: "ordered"}, {list: "bullet"}],
["bold", "italic", "underline"],
[{color: []}, {backgrond: []}],
[{script: "sub"}, {script: "super"}],
[{align: []}],
["image", "blockquote", "code-block"],
["clean"],
]
export default function TextEditor() {
const [socket, setSocket] = useState();
const [quill, setQuill] = useState();
useEffect(() => {
const s = io("http://localhost:3001")
setSocket(s)
return () => {
s.disconnect()
}
}, [])
useEffect(() => {
if (socket == null || quill == null) return
const handler = (delta, oldDelta, source) => {
socket.emit("send-changes", delta)
}
quill.on('text-change', handler)
return () => {
quill.off('text-change', handler)
}
}, [socket, quill])
const wrapperRef = useCallback((wrapper) => {
if (wrapper == null) return
wrapper.innerHTML = ''
const editor = document.createElement('div')
wrapper.append(editor)
const q = new Quill(editor, { theme: 'snow', modules: {
toolbar: TOOLBAR_OPTIONS}})
setQuill(q)
}, [])
return (
<div className="container" ref={wrapperRef}></div>
)
}
*serverconst io = require('socket.io')(3001, {
cors: {
origin: 'http://localhost: 3000',
methods: ['GET', 'POST']
}
})
io.on("connection", socket => {
socket.on('send-changes', delta => {
console.log("connected")
})
})
最終バージョン
https://coding-hwije.tistory.com/24(参照サイト)
https://github.com/WebDevSimplified/google-docs-clone/blob/main/client/src/TextEditor.js
clientimport { useCallback, useEffect, useState } from "react"
import Quill from "quill"
import "quill/dist/quill.snow.css"
import { io } from "socket.io-client"
import { useParams } from "react-router-dom"
//setInterval() 일정한 시간 간격으로 작업을 수행하기 위해 사용
const SAVE_INTERVAL_MS = 2000
//위의 툴바 부분
const TOOLBAR_OPTIONS = [
[{ header: [1, 2, 3, 4, 5, 6, false] }],
[{ font: [] }],
[{ list: "ordered" }, { list: "bullet" }],
["bold", "italic", "underline"],
[{ color: [] }, { background: [] }],
[{ script: "sub" }, { script: "super" }],
[{ align: [] }],
["image", "blockquote", "code-block"],
["clean"],
]
export default function TextEditor() {
// const params = useParams()
const { id: documentId } = useParams() //뭔가 파라미터...주소...쓴다는 그 느낌
const [socket, setSocket] = useState()
const [quill, setQuill] = useState()
useEffect(() => {
const s = io("http://localhost:3001")
setSocket(s)
return () => {
s.disconnect()
}
}, [])
useEffect(() => {
if (socket == null || quill == null) return
//최초 1번 실행되는 once메소드, 첫번째 데이터에 대해서만 데이터가 되돌려지는 예제
socket.once("load-document", document => {
quill.setContents(document)
quill.enable()
})
socket.emit("get-document", documentId)
}, [socket, quill, documentId])
useEffect(() => {
if (socket == null || quill == null) return
const interval = setInterval(() => { //일정한 시간 간격으로 작업을 수행하기 위해 사용
socket.emit("save-document", quill.getContents())
}, SAVE_INTERVAL_MS)
//socket.emit 데이터 보낼 때
//서버의 save-document 이벤트명을 찾아 보내진다
//클라이언트의 contents를 보냄?
return () => {
clearInterval(interval)
}
}, [socket, quill])
useEffect(() => {
if (socket == null || quill == null) return
const handler = delta => {
quill.updateContents(delta)
}
socket.on("receive-changes", handler)
return () => {
socket.off("receive-changes", handler)
}
}, [socket, quill])
useEffect(() => {
if (socket == null || quill == null) return
const handler = (delta, oldDelta, source) => {
if (source !== "user") return
socket.emit("send-changes", delta)
}
quill.on("text-change", handler)
return () => {
quill.off("text-change", handler)
}
}, [socket, quill])
//useCallback 특정함수를 새로 만들지 않고 재사용하고 싶을 때 사용
const wrapperRef = useCallback(wrapper => {
if (wrapper == null) return
wrapper.innerHTML = ""
const editor = document.createElement("div")
wrapper.append(editor)
const q = new Quill(editor, {
theme: "snow",
modules: { toolbar: TOOLBAR_OPTIONS },
})
q.disable()
q.setText("Loading...")
setQuill(q)
}, [])
return <div className="container" ref={wrapperRef}></div>
}
serverconst mongoose = require("mongoose")
const Document = require("./Document")
mongoose.connect("mongodb://localhost/google-docs-clone", {
useNewUrlParser: true,
useUnifiedTopology: true,
useFindAndModify: false,
useCreateIndex: true,
})
const io = require("socket.io")(3001, {
cors: {
origin: "http://localhost:3000",
methods: ["GET", "POST"],
},
})
const defaultValue = ""
io.on("connection", socket => {
socket.on("get-document", async documentId => { //socket.on 데이터 받기
const document = await findOrCreateDocument(documentId)
socket.join(documentId)
//socket.join 룸을 만든다
//받아온 documentId라는 이름의 새로운 룸에 접속했다
socket.emit("load-document", document.data)
socket.on("send-changes", delta => {
socket.broadcast.to(documentId).emit("receive-changes", delta)
})
socket.on("save-document", async data => {
await Document.findByIdAndUpdate(documentId, { data })
})
})
})
async function findOrCreateDocument(id) {
if (id == null) return
const document = await Document.findById(id)
if (document) return document
return await Document.create({ _id: id, data: defaultValue })
}
Reference
この問題について(ソケット学習), 我々は、より多くの情報をここで見つけました
https://velog.io/@slamdunk11/socket-공부
テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol
import { useCallback, useEffect, useState } from "react"
import Quill from "quill"
import "quill/dist/quill.snow.css"
import { io } from "socket.io-client"
import { useParams } from "react-router-dom"
//setInterval() 일정한 시간 간격으로 작업을 수행하기 위해 사용
const SAVE_INTERVAL_MS = 2000
//위의 툴바 부분
const TOOLBAR_OPTIONS = [
[{ header: [1, 2, 3, 4, 5, 6, false] }],
[{ font: [] }],
[{ list: "ordered" }, { list: "bullet" }],
["bold", "italic", "underline"],
[{ color: [] }, { background: [] }],
[{ script: "sub" }, { script: "super" }],
[{ align: [] }],
["image", "blockquote", "code-block"],
["clean"],
]
export default function TextEditor() {
// const params = useParams()
const { id: documentId } = useParams() //뭔가 파라미터...주소...쓴다는 그 느낌
const [socket, setSocket] = useState()
const [quill, setQuill] = useState()
useEffect(() => {
const s = io("http://localhost:3001")
setSocket(s)
return () => {
s.disconnect()
}
}, [])
useEffect(() => {
if (socket == null || quill == null) return
//최초 1번 실행되는 once메소드, 첫번째 데이터에 대해서만 데이터가 되돌려지는 예제
socket.once("load-document", document => {
quill.setContents(document)
quill.enable()
})
socket.emit("get-document", documentId)
}, [socket, quill, documentId])
useEffect(() => {
if (socket == null || quill == null) return
const interval = setInterval(() => { //일정한 시간 간격으로 작업을 수행하기 위해 사용
socket.emit("save-document", quill.getContents())
}, SAVE_INTERVAL_MS)
//socket.emit 데이터 보낼 때
//서버의 save-document 이벤트명을 찾아 보내진다
//클라이언트의 contents를 보냄?
return () => {
clearInterval(interval)
}
}, [socket, quill])
useEffect(() => {
if (socket == null || quill == null) return
const handler = delta => {
quill.updateContents(delta)
}
socket.on("receive-changes", handler)
return () => {
socket.off("receive-changes", handler)
}
}, [socket, quill])
useEffect(() => {
if (socket == null || quill == null) return
const handler = (delta, oldDelta, source) => {
if (source !== "user") return
socket.emit("send-changes", delta)
}
quill.on("text-change", handler)
return () => {
quill.off("text-change", handler)
}
}, [socket, quill])
//useCallback 특정함수를 새로 만들지 않고 재사용하고 싶을 때 사용
const wrapperRef = useCallback(wrapper => {
if (wrapper == null) return
wrapper.innerHTML = ""
const editor = document.createElement("div")
wrapper.append(editor)
const q = new Quill(editor, {
theme: "snow",
modules: { toolbar: TOOLBAR_OPTIONS },
})
q.disable()
q.setText("Loading...")
setQuill(q)
}, [])
return <div className="container" ref={wrapperRef}></div>
}
const mongoose = require("mongoose")
const Document = require("./Document")
mongoose.connect("mongodb://localhost/google-docs-clone", {
useNewUrlParser: true,
useUnifiedTopology: true,
useFindAndModify: false,
useCreateIndex: true,
})
const io = require("socket.io")(3001, {
cors: {
origin: "http://localhost:3000",
methods: ["GET", "POST"],
},
})
const defaultValue = ""
io.on("connection", socket => {
socket.on("get-document", async documentId => { //socket.on 데이터 받기
const document = await findOrCreateDocument(documentId)
socket.join(documentId)
//socket.join 룸을 만든다
//받아온 documentId라는 이름의 새로운 룸에 접속했다
socket.emit("load-document", document.data)
socket.on("send-changes", delta => {
socket.broadcast.to(documentId).emit("receive-changes", delta)
})
socket.on("save-document", async data => {
await Document.findByIdAndUpdate(documentId, { data })
})
})
})
async function findOrCreateDocument(id) {
if (id == null) return
const document = await Document.findById(id)
if (document) return document
return await Document.create({ _id: id, data: defaultValue })
}
Reference
この問題について(ソケット学習), 我々は、より多くの情報をここで見つけました https://velog.io/@slamdunk11/socket-공부テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol