如何在挂载时插入/附加一个React组件

huangapple go评论73阅读模式
英文:

How do you insert/append a react Component on mount

问题

在挂载时,我想要插入/附加一个组件,可以作为子节点或同级节点。

我找到的在线解决方案都没有奏效:

  • ReactDOM.render()
    • 这会用<Component />替换整个节点及其子节点。
  • .insertAdjacentElement()
    • 我收到类型错误消息:Argument of type 'ReactNode' is not assignable to parameter of type 'Element'.
  • .appendChild()
    • 我收到错误消息:Argument of type 'JSX.Element' is not assignable to parameter of type 'Node'.
  • .append()
    • 我收到错误消息:Argument of type 'Element' is not assignable to parameter of type 'string | Node'.

例如:

React.useEffect(() => {
  // 使 <Component /> 在 DOM 中出现的代码
}, []);

<div>
  <div>
    <p>Something</p>
    {/* 在挂载时,<Component /> 被插入到这里 */}
  </div>
</div>

[为了提供更多细节进行编辑]:

我正在寻找一种解决方案,我不必在return ();内输入任何内容。

所有插入<Component />的功能都需要在那之上完成。

英文:

Like the title says, on mount I want to insert/append a Component, either as a child or sibling.

Things I've found online that haven't worked:

  • ReactDOM.render()
    • This replaces the whole node and its children with the &lt;Component /&gt;.
  • .insertAdjacentElement()
    • I get the type error Argument of type &#39;ReactNode&#39; is not assignable to parameter of type &#39;Element&#39;.
  • .appendChild()
    • I get the error Argument of type &#39;JSX.Element&#39; is not assignable to parameter of type &#39;Node&#39;.
  • .append()
    • I get error Argument of type &#39;Element&#39; is not assignable to parameter of type &#39;string | Node&#39;.

For example:

React.useEffect(() =&gt; {
  // Code that makes &lt;Component /&gt; appear in DOM
}, []);

&lt;div&gt;
  &lt;div&gt;
    &lt;p&gt;Something&lt;/p&gt;
    {/* On mount &lt;Component /&gt; is inserted here */}
  &lt;/div&gt;
&lt;/div&gt;

[Edited for more detail]:

I'm looking for a solution where I don't have to enter anything inside of the return ();.

All functionality to insert the &lt;Component /&gt; needs to be done above that.

答案1

得分: 1

你可以这样处理:

  1. 使用一个名为 state 的布尔标志来处理组件的可见性。
  2. JSX 部分返回动态内容(也是一个 React 组件),并加入一个条件。
  3. 使用 useEffect 钩子,在首次渲染后执行一次作用域,将可见性更改为 true。
  4. 创建一个 clickHandler 函数,用于切换可见性的状态(开/关),并将其与按钮关联。

以下是代码示例:

import { useEffect, useState } from 'react';

const DynamicContent = () => <div>动态内容</div>;

const MyComponent = () => {
  const [isVisible, setVisibility] = useState(false); // 1

  useEffect(() => {
    setVisibility(true); // 3
  }, []);

  const handleClick = () => {
    setVisibility(!isVisible); // 4
  };

  return (
    <div className="my-component">
      <h1 className="my-component__dynamic-content">这是动态内容</h1>
      <button onClick={handleClick}>切换可见性</button>
      {isVisible && <DynamicContent />} // 2
    </div>
  );
};

export default MyComponent;

注意我正在使用:

  • AtomicDesign 文件夹结构
  • BEM className 模式
英文:

You could handle it like this:

  1. use a state boolean flag to handle the component's visibility
  2. in the JSX part return the dynamic content(which is also a react component), with a condition
  3. use an useEffect hook to execute a scope just once after the first render, to change the visibility to true
  4. create a clickHandler that switches the visibility on/off, and link it to a button

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-js -->

import { useEffect, useState } from &#39;react&#39;;

const DynamicContent = () =&gt; &lt;div&gt;dynamic content&lt;/div&gt;;

const MyComponent = () =&gt; {
  const [isVisible, setVisibility] = useState(false);        //1

  useEffect(() =&gt; {
    setVisibility(true);                                     //3
  }, []);

  const handleClick = () =&gt; {
    setVisibility(!isVisible);                               //4
  };

  return (
    &lt;div className=&quot;my-component&quot;&gt;
      &lt;h1 className=&quot;my-component__dynamic-content&quot;&gt;This is dynamic content&lt;/h1&gt;
      &lt;button onClick={handleClick}&gt;change visibility&lt;/button&gt;
      {isVisible &amp;&amp; &lt;DynamicContent /&gt;}                      //2
    &lt;/div&gt;
  );
};

export default MyComponent;

<!-- end snippet -->

note that I am using:

  • AtomicDesign folder structure
  • BEM className pattern

答案2

得分: 0

大部分列出的方法都是DOM API调用(例如insertAdjacentElementappendChild()等)。之所以出现所有这些类型错误,是因为你不能混合使用React和DOM元素。React使用自己的虚拟DOM,在其渲染机制之外进行操作是一个巨大的反模式。

虽然<Component />看起来像是一个DOM元素,但实际上JSX在幕后编译成函数调用。你可以尝试像这样直接在你的效果中渲染HTML:

const textnode = document.createTextNode("Water");
node.appendChild(textnode);

但这将不会被视为React,你将失去状态管理功能。正确的做法是在你的render()方法中使用条件语句,就像其他答案建议的那样。

英文:

Most of the methods listed are DOM api calls (insertAdjacentElement, appendChild() etc.) The reason you're getting all these type errors is because you can't mix and match React and DOM elements like that. React uses it's own virtual dom and doing something outside it's rendering mechanisms is a huge anti-pattern.

&lt;Component /&gt; although this looks like a DOM element, JSX actually compiles to function calls behind the scenes. You could potentially do something like this to render HTML directly in your effect.

const textnode = document.createTextNode(&quot;Water&quot;);
node.appendChild(textnode);

But this will not be treated as React and you'll lose the state management functionality. The proper way to do this is to use a conditional in your render() method like the other answers suggested.

huangapple
  • 本文由 发表于 2023年7月18日 06:12:35
  • 转载请务必保留本文链接:https://go.coder-hub.com/76708392.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定