【问题标题】:Render Variable Styled Component From Context从上下文渲染可变样式的组件
【发布时间】:2021-03-10 14:06:19
【问题描述】:

您好,我正在制作一个网站构建应用程序,它使用样式化的组件和表单将数据呈现到页面的各个部分。所以我决定我所有的样式组件都将是默认导出,然后导入到上下文中,然后在打开时加载到表单中。 Then from a select menu the user gets a map of all the possible components to render and when an option is selected a string reference filters the component array down to the called function and then adds all the other data and then displays it on screen.当我启动时,我收到此错误:“React.jsx:类型无效 - 需要一个字符串(用于内置组件)或一个类/函数(用于复合组件)但得到:。你是否不小心导出了一个 JSX 文字而不是一个组件?”

以下是所有部分:

BurgerMenu.js

import React, { useState, useRef } from "react";
import { ThemeProvider } from "styled-components";
import { useOnClickOutside } from "../../state/useOnClickOutside";
import { GlobalStyles } from "../../state/globals";
import { useTheme } from "../../state/useTheme";
import Hamburger from "./Hamburger";
import Menu from "./Menu";
const BurgerMenu = () => {
  const [open, setOpen] = useState(false);
  const node = useRef();
  useOnClickOutside(node, () => setOpen(false));
  const { theme } = useTheme();
  return (
    <ThemeProvider theme={theme}>
      <>
        <GlobalStyles />
        <div ref={node}>
          <Hamburger open={open} setOpen={setOpen} />
          <Menu open={open} setOpen={setOpen} />
        </div>
      </>
    </ThemeProvider>
  );
};
export default BurgerMenu;

组件上下文:

import BurgerMenu from "../header/Hamburger/BurgerMenu";
 const components = [{
      name: "BurgerMenu",
      func: BurgerMenu,
      els: ["a", "a", "a", "a", "a", "a"],
    }]

Site Form(调用组件上下文的地方)

const { components } = useComponentContext();
const [mount, setMount] = useState('')
<select name='component' onChange={(e) => setMount(e.target.value)}>
    {components.map((component) => (
          <option key={component.name} value={component.name}>
             {component.name}
           </option>
      ))}
</select>
<button
   className='btn primary btn-block'
   onClick={() => {
       convertStringToComponent(mount);
       setTimeout(setLoaded((prevState) => !prevState),2000)}}>
              Add Component
</button>

函数convertStringToComponent

const convertStringToComponent = (mount, compStyle) => {
    const ComponentName = components
      .filter((comp) => comp.name === mount)
      .map(({ func }) => func)[0];

    return (
      <ComponentName
        content={content}
        font={font}
        pallet={pallet}
        h={h}
        icon={icon}
        p={p}
        vid={vid}
        img={img}
        a={a}
        li={li}
        button={button}></ComponentName>
    );
  };

const VariableComponent = convertStringToComponent(mount);

然后在不同的组件中调用它

 {loaded === true && <VariableComponent />}

任何帮助都会很棒!

【问题讨论】:

    标签: javascript reactjs styled-components


    【解决方案1】:

    问题在于您如何使用 convertStringToComponent 的函数返回值。

    当您调用时,convertStringToComponent 您将返回一个组件实例,该实例是

    <ComponentName
        content={content}
        font={font}
        pallet={pallet}
        h={h}
        icon={icon}
        p={p}
        vid={vid}
        img={img}
        a={a}
        li={li}
        button={button}></ComponentName>
    

    现在,在渲染时,您尝试再次使用它来创建一个实例 eout

    {loaded === true && <VariableComponent />}
    

    而不是

     {loaded === true && VariableComponent}
    

    但是,还有另一个问题,当您调用 convertStringToComponent 时,您不应该尝试将结果存储在变量中并导出它,而应该将其存储在实例状态中并呈现它。

    构建代码的更好方法是

    export const convertStringToComponent = (mount, compStyle) => {
        const ComponentName = components
          .filter((comp) => comp.name === mount)
          .map(({ func }) => func)[0];
        
        return  (otherProps) => (
          <ComponentName
            {...otherProps}
            content={content}
            font={font}
            pallet={pallet}
            h={h}
            icon={icon}
            p={p}
            vid={vid}
            img={img}
            a={a}
            li={li}
            button={button}></ComponentName>
        );
      };
    

    现在你可以像这样使用它了

    const [VariableComponent, setVariableComponent] = useState(null);
    
    <button
       className='btn primary btn-block'
       onClick={() => {
           const comp = convertStringToComponent(mount);
           setVariableComponent(comp);
           setTimeout(setLoaded((prevState) => !prevState),2000)}}>
                  Add Component
    </button>
    
    
    {isLoaded && <VariableComponent />}
    

    【讨论】:

    • 嘿,这有一个作用,虽然它不是 JSX 中的 ,但它仍然像您在 VariableComponent 的第一部分中所做的那样。谢谢!
    • @MickeyGray 为了使用&lt;VariableComponent /&gt;,您也必须将convertStringToComponent 的实现更改为我在回答中提到的内容
    • 只是让您知道我直接复制并粘贴了您的第二个示例,并且 出现错误,而不是带有 {isLoaded &amp;&amp; &lt;VariableComponent /&gt;} 的 VariableComponent 出现错误
    猜你喜欢
    • 2018-07-08
    • 1970-01-01
    • 2020-12-08
    • 2017-08-25
    • 1970-01-01
    • 2019-02-24
    • 1970-01-01
    • 1970-01-01
    • 2015-05-30
    相关资源
    最近更新 更多