英文:
Rendering React Components from String
问题
我试图根据用户输入的字符串动态创建多个 React 组件。每个字母都应该作为单独的组件呈现。
我的计划是从字符串创建一个数组,然后对其进行映射,返回一个包含每个组件的新数组。
我的主要问题是将字母(字符串)转换为组件的名称。
我曾尝试使用 'eval' 找到解决方案,但在生产环境中进行了压缩时会失败。
(*元素类型无效:期望一个字符串(用于内置组件)或一个类/函数(用于组合组件),但得到了:数字。*)
英文:
I'm trying to create multiple React components dynamically from a string entered by the user. Each letter is supposed to be rendered as a separate component.
My plan was to create an array from the string and map over it returning each component in a new array.
My main issue is to convert the letter (string) into the component's name.
import React from 'react'
import './App.css'
import A from './ComponentA'
import B from './ComponentB'
import C from './ComponentC'
const userInput = "ABC"
const userInputArray = userInput.split("")
const components = userInputArray.map((comp, index) => {
return (
React.createElement(eval(comp), { key: [index]})
)
})
function App() {
return (
<>
{ components }
</>
)
}
export default App
I thought I found a solution using 'eval' but it fails when minified in production.
(Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: number.)
答案1
得分: 2
使用eval()
真的没有任何理由,你可以简单地使用字典存储你的组件引用,然后相应地渲染。
请注意,我已经使用i
作为键,但你真的不应该使用它,而是依赖于一个稳定的、唯一的标识符。
import A from "./ComponentA";
import B from "./ComponentB";
import C from "./ComponentC";
// 注意:添加了 'D' 以测试不存在的组件
const userInput = "ABCD";
const userInputArray = userInput.split("");
const components = { A, B, C };
export default function App() {
return userInputArray.map((component, i) => {
const Component = components[component];
if (!Component) return <></>;
return <Component key={i} />;
});
}
然而,我建议你利用React的懒加载和Suspense
特性,这样如果用户输入数组不需要所有组件,就不必一次性加载它们。这是一个稍微高级一些的示例:
- 它允许你输入动态字符串,解析后加载必要的组件
- 使用React.Suspense + React.lazy执行动态加载
import { lazy, Suspense, useState } from "react";
const components = {
A: lazy(() => import("./ComponentA")),
B: lazy(() => import("./ComponentB")),
C: lazy(() => import("./ComponentC"))
};
export default function App() {
const [userInput, setUserInput] = useState("ABCD");
return (
<>
<input
type="text"
value={userInput}
onChange={(e) => setUserInput(e.currentTarget.value)}
/>
<Suspense fallback="Loading...">
{userInput.split("").map((component, i) => {
const Component = components[component.toUpperCase()];
if (!Component) return <></>;
return <Component key={i} />;
})}
</Suspense>
</>
);
}
英文:
There is really no reason to use eval()
at all: you can simply use a dictionary to store your component references, and then render it accordingly.
Note that I have used i
as a key, but you really should not use it but instead rely on a stable, unique identifier.
import A from "./ComponentA";
import B from "./ComponentB";
import C from "./ComponentC";
// NOTE: Added 'D' to test for component that doesn't exist
const userInput = "ABCD";
const userInputArray = userInput.split("");
const components = { A, B, C };
export default function App() {
return userInputArray.map((component, i) => {
const Component = components[component];
if (!Component) return <></>;
return <Component key={i} />;
});
}
However, what I would recommend is that you take advantage of React lazy loading and suspense feature, so that you don't have to load all components at once if the user input array does not need all of them. It is little more advanced, but here is another proof-of-concept example:
- It allows you to input dynamic string that is parsed to load in the necessary components
- It uses React.Suspense + React.lazy to perform dynamic loading
import { lazy, Suspense, useState } from "react";
const components = {
A: lazy(() => import("./ComponentA")),
B: lazy(() => import("./ComponentB")),
C: lazy(() => import("./ComponentC"))
};
export default function App() {
const [userInput, setUserInput] = useState("ABCD");
return (
<>
<input
type="text"
value={userInput}
onChange={(e) => setUserInput(e.currentTarget.value)}
/>
<Suspense fallback="Loading...">
{userInput.split("").map((component, i) => {
const Component = components[component.toUpperCase()];
if (!Component) return <></>;
return <Component key={i} />;
})}
</Suspense>
</>
);
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论