Javascript React门户输入更改将删除元素

Javascript React门户输入更改将删除元素,javascript,reactjs,react-hooks,Javascript,Reactjs,React Hooks,我创建这支钢笔是为了演示它: 基本上我有这个门户: const ChatArea = ({ children }) => { const el = document.createElement("div"); el.classList.add('chatbox') const root = document.getElementById("rootus"); useEffect(() => { root.appendChild(el); return

我创建这支钢笔是为了演示它:

基本上我有这个门户:

const ChatArea = ({ children }) => {
  const el = document.createElement("div");
  el.classList.add('chatbox')
  const root = document.getElementById("rootus");

  useEffect(() => {
    root.appendChild(el);
    return () => root.removeChild(el);
  }, []);

  return createPortal(children, el);
};
并使用类似于:

const ChatBox = () => {
  const [ reply, setReply ] = useState('');
  const handleReply = (e) => {
    e.preventDefault();
    setReply(e.target.value);
  }
  return (
    <ChatArea>
      <div className="chat-title">Bot Convo</div>

      <div className="chat-convo"></div>

      <div className="chat-reply">
        <input type="text" value={reply} onChange={handleReply} />
        <button>Send</button>
      </div>
    </ChatArea>
  )
}
const ChatBox=()=>{
const[reply,setReply]=useState(“”);
常量handleReply=(e)=>{
e、 预防默认值();
setReply(即目标值);
}
返回(
机器人车队
发送
)
}

由于某种原因,当你开始键入聊天框的主体时,它似乎消失了。。。我已将日志放入
useffect
中,以查看是否是这导致了它,但它没有显示我的想法,这里有两个问题:

第一个问题是

useEffect(() => {
    root.appendChild(el);
    return () => root.removeChild(el);
  }, []);
现在根据钩子原理,依赖项应该与钩子中使用的变量相匹配。如果未使用react,则下次不会运行该效果

因此,在您的情况下,当您单击打开聊天时,它会打开聊天框。效果运行并使用输入框呈现门户

当你打完第一个字母后,发生了一次变化

它触发了ChatArea的重新渲染器,理想情况下,它应该再次运行该效果,但没有运行,因为依赖项数组为空,react不知道何时重新渲染。因此,该效果第一次在ChatArea运行UI的位置运行,下一次,该效果没有运行,因为依赖项数组为空

这一行:

返回createPortal(子项,el);//是指创建的新el 但不附加到DOM。因此,在聊天盒内的UI上看不到任何内容

请参阅此链接:常见问题解答部分它们很棒:)

第二期:

理想情况下,不应该每次都创建新的div。在连续的重新渲染器中持久化“div”元素

看看这个实现:我知道还有其他的实现方法。 欢迎反馈

const{
提供,
createPortal
}=反应性;
常数{
useState,
使用效果,
useRef
}=反应;
施工区=({
儿童
}) => {
const el=document.createElement(“div”);
el.classList.add('chatbox')
//上述el在每个渲染中都会不同
//root将保持不变,理想情况下root和chatdiv应该作为道具传递
const root=document.getElementById(“rootus”);
//此val和setVal用于切换渲染后的图表区域
//chatDiv已更新
const[val,setVal]=useState(真)
const chatDiv=useRef(空)
//首先使用effect保存div
useffect(()=>{
如果(!chatDiv.current){
chatDiv.current=el
setVal(!val)
}
},[chatDiv])
useffect(()=>{
root.appendChild(chatDiv.current);
return()=>{
返回root.removeChild(chatDiv.current)
};//您正在删除它
},[chatDiv,root]);
if(当前聊天室){
返回createPortal(子项,chatDiv.current)
}
返回空
//在你的情况下,因为返回首先发生,并发现了el
};
常量聊天框=()=>{
const[reply,setReply]=useState(“”);
常量handleReply=(e)=>{
e、 预防默认值();
setReply(即目标值);
}
报税表(<
聊天区>
<
div className=“聊天标题”>机器人车队
<
div className=“聊天车队”>
< div className=“聊天回复”> < 输入类型=“文本” 值={ 回复 } onChange={ 手忙脚乱 } /> < 按钮>发送< /div>< /聊天区> ) } 常量NavBar=({})=>(< div className=“navbar”> < div>主页
< div>某处
< /div> ); 常量Main=()=>{ const[showChat,setShowChat]=useState(false); const openChat=()=>{ 设置ShowChat(true); }; const chatterbox=showChat?():null; 报税表(< div className=“container”> < h2>Main< p> 读者在查看页面布局时会被页面的可读内容分散注意力,这是一个早已确定的事实 使用Lorem Ipsum是因为它具有或多或少的正态分布 信件,而不是使用“此处内容,此处内容”,使其看起来像可读的英语。许多桌面发布软件包和网页编辑器现在使用Lorem Ipsum作为它们的 默认模型文本和搜索 对于“lorem ipsum” 这些年来,各种版本不断演变,有时是偶然的,有时是故意的(注入幽默等)< /p>< p样式={ { 显示:“flex”, 为内容辩护:“中心” } } > < 按钮onClick={ openChat }>打开聊天室< /p>< p样式={ { 显示:“flex”, flexDirection:“列”, 辩护内容:“中心”, 背景颜色:“红色” } } > { 喋喋不休 }

< /div> ); }; 常量App=({})=>(< div className=“应用程序”> < 导航栏/> < Main/> < /div> ); render(,document.getElementById(“rootus”)
正文{
字体系列:雷威;
}
* {
框大小:边框框;
}
#根{
位置:相对位置;
高度:100vh;
显示器:flex;
证明内容:中心;
}
navbar先生{
显示器:flex;
证明内容:中心;
}
.navbar>div{
填充:10px;
}
.navbar>div:悬停{
背景颜色:灰色;
光标:指针;
}
.集装箱{
宽度:960px;
}
.app{
显示器:flex;
弯曲方向:立柱;
对齐项目:居中;
}
.聊天室{
宽度:400px;
高度:200px;
位置:绝对位置;
底部:0;
边框:2件纯黑;
背景:白色;
显示器:flex;
弯曲方向:立柱;
}
.聊天标题{
背景:黑色;
颜色:白色;
}
.聊天车队{
弹性:1;
显示器:flex;
}
.聊天回复{
显示器:flex;
边框顶部:1件纯黑;
}
.chat回复>输入{
宽度:80%;
填充:8px;
边界:无;
大纲:无;
}
.聊天回复>按钮{
大纲:无;
边界:无;
弹性:1;
}