React UseEffect 不适用于 firepad 和 firebase
React UseEffect is not working with the firepad and firebase
我正在尝试使用来自 firebase 的用户名并在 FirepadUserList 中创建一个用户。代码看起来像这样
import { useRef, useEffect,useState } from 'react';
import 'codemirror/lib/codemirror.css'
import CodeMirror from 'codemirror';
import firebase from "firebase/compat";
import 'firepad/dist/firepad.css'
import classes from './Document.module.scss'
import './editor.css';
import FirepadUserList from '../../components/UserList/firepad-userlist';
import '../../components/UserList/firepad-userlist.css'
import Loading from '../../components/Loading';
import {useSession} from "../../firebase/AuthProvider";
type User = firebase.User | null;
type Loading = boolean;
function Editor() {
const {user, loading} = useSession();
const username = user?.displayName;
const editorRef = useRef<HTMLDivElement>(null);
let userId = Math.floor((Math.random() * 10) + 1);
useEffect(() => {
const codeMirror = CodeMirror(editorRef.current!, { lineWrapping: true });
window.CodeMirror = CodeMirror;
const Firepad = require('firepad');
const firepadRef = getExampleRef();
const firepad = Firepad.fromCodeMirror(firepadRef, codeMirror,
{ richTextToolbar: true, richTextShortcuts: true, userId:userId.toString()});
FirepadUserList.fromDiv(firepadRef.child('users'),
document.getElementById('userlist'), userId.toString(),username);
firepad.on('ready', function () {
if (firepad.isHistoryEmpty()) {
firepad.setHtml("<div>Start typing</div>");
}
});
}, [username]);
function getExampleRef() {
let ref = firebase.database().ref();
const hash = window.location.hash.replace(/#/g, '');
if (hash) {
ref = ref.child(hash);
} else {
ref = ref.push(); // generate unique location.
window.location.href = window.location + '#' + ref.key;
}
if (typeof console !== 'undefined') {
console.log('Firebase data: ', ref.toString());
}
return ref;
}
return (
<>
<div id="userlist" className={classes.userlist}></div>
<div className={classes.editor} ref={editorRef}></div>
</>
);
}
export default Editor;
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
但是如果我在 useEffect 中使用 username 变量,codeMirror 编辑器和 FirepadUserList 都会渲染两次,并且在线显示另一个用户,而它应该只有一个
但是如果使用字符串对用户名进行硬编码,如 username = "Fahim Khan",则一切正常。请注意,我使用的是 .tsx 扩展名。
好的,我得到了答案。问题是获取用户名的延迟。所以 useEffect 是 运行 两次。如果将代码包装在 useEffect 条件内 if(username != null) 它工作正常
我正在尝试使用来自 firebase 的用户名并在 FirepadUserList 中创建一个用户。代码看起来像这样
import { useRef, useEffect,useState } from 'react';
import 'codemirror/lib/codemirror.css'
import CodeMirror from 'codemirror';
import firebase from "firebase/compat";
import 'firepad/dist/firepad.css'
import classes from './Document.module.scss'
import './editor.css';
import FirepadUserList from '../../components/UserList/firepad-userlist';
import '../../components/UserList/firepad-userlist.css'
import Loading from '../../components/Loading';
import {useSession} from "../../firebase/AuthProvider";
type User = firebase.User | null;
type Loading = boolean;
function Editor() {
const {user, loading} = useSession();
const username = user?.displayName;
const editorRef = useRef<HTMLDivElement>(null);
let userId = Math.floor((Math.random() * 10) + 1);
useEffect(() => {
const codeMirror = CodeMirror(editorRef.current!, { lineWrapping: true });
window.CodeMirror = CodeMirror;
const Firepad = require('firepad');
const firepadRef = getExampleRef();
const firepad = Firepad.fromCodeMirror(firepadRef, codeMirror,
{ richTextToolbar: true, richTextShortcuts: true, userId:userId.toString()});
FirepadUserList.fromDiv(firepadRef.child('users'),
document.getElementById('userlist'), userId.toString(),username);
firepad.on('ready', function () {
if (firepad.isHistoryEmpty()) {
firepad.setHtml("<div>Start typing</div>");
}
});
}, [username]);
function getExampleRef() {
let ref = firebase.database().ref();
const hash = window.location.hash.replace(/#/g, '');
if (hash) {
ref = ref.child(hash);
} else {
ref = ref.push(); // generate unique location.
window.location.href = window.location + '#' + ref.key;
}
if (typeof console !== 'undefined') {
console.log('Firebase data: ', ref.toString());
}
return ref;
}
return (
<>
<div id="userlist" className={classes.userlist}></div>
<div className={classes.editor} ref={editorRef}></div>
</>
);
}
export default Editor;
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
但是如果我在 useEffect 中使用 username 变量,codeMirror 编辑器和 FirepadUserList 都会渲染两次,并且在线显示另一个用户,而它应该只有一个
但是如果使用字符串对用户名进行硬编码,如 username = "Fahim Khan",则一切正常。请注意,我使用的是 .tsx 扩展名。
好的,我得到了答案。问题是获取用户名的延迟。所以 useEffect 是 运行 两次。如果将代码包装在 useEffect 条件内 if(username != null) 它工作正常