Using for loops and switch cases in React to dynamically render different components
我正在尝试使用 React JSX 中的 switch case 有条件地渲染组件。我正在尝试构建从特定 json 结构读取并呈现数据的东西。由于可能有许多不同的组件和数据,我试图动态呈现它。请参阅下面的代码,我没有收到任何错误,但组件没有被渲染。在我的 html 里面,我只能看到 .这意味着循环不工作。我尝试在 vanilla JS 中使用相同的循环并且它有效。
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 |
var myPackage = [{
sectionInfo:[{ elementType: 1, text:”This is text from element type 1″ }] }, { sectionInfo:[{ elementType: 2, text:”This is text from element type 2″ }] }]; var App = React.createClass({ render: function(){ |
编辑:对代码做了一些补充,现在我面临一个新问题。这是新代码:
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
var App = React.createClass({
render: function(){ |
我想每次都在一个 div 中渲染。所以如果一个部分有超过 3 个元素,那么所有 3 个元素都必须在一个 div 内。
- elements 是列表列表,但应该是组件列表。尝试使用 elements = Array.prototype.concat.apply([], elements) 将其展平
在 JSX 中做一个 switch case 如下:
1
2 3 4 5 6 7 8 9 10 11 12 13 14 |
{{
sectionA: ( <SectionAComponent /> ), sectionB: ( <SectionBComponent /> ), sectionC: ( <SectionCComponent /> ), default: ( <SectionDefaultComponent /> ) }[section]} |
- 这如何处理默认值?
- 在最后一行,如果您希望 sectionC 成为默认值,您可以执行 [section ||sectionC] 以获得更好的覆盖率。
- @frandroid 默认需要放在开关的顶部。自上而下评估中的最终匹配是将返回的匹配。
- @Isaac我认为一个很好的选择是在右括号 [section] || <SectionCComponent /> 之后添加默认值
- @BlakePlumb 我认为这不是一个很好的选择……重复的代码?
- [部分|| sectionC] 不等同于默认值 – 只有当 section 本身是假的,而不是 [section] 时,内部表达式才会评估为 sectionC。如果您需要适当的默认行为,我认为您需要使用 IIFE。
- 我喜欢它,但性能可能不如开关/更贵?即使只使用一个,是否会评估所有”分支”?
- 实际上回到这个问题,根据值(类型)渲染 React 组件的最佳方法是使用所谓的”Dot.Notation”reactjs.org/docs/…,这比条件切换案例要好得多
- 这看起来像一个”易于阅读”的解决方案,但我会考虑使用它,因为它可能会导致内存泄漏。每次调用渲染方法时,它都会在内存中创建一个对象并从中获取正确的值。
- 这不是内存泄漏,只是比普通开关使用更多的内存。这是因为它是一个对象字面量,它通过键名引用其成员之一。理论上,对象中的所有组件都会被创建,但取决于解释器,它可能会被优化掉。
对于内联/未创建新函数,可以这样使用
1
2 3 4 5 6 7 8 |
{(() => {
switch (myObj1.elementType) { case ‘pantulan’: return <Component1 text = {myObj1.text} key={ key } /> default : null } })()} |
- 最好创建一个新函数,因为在您的情况下,每次呈现 html 时都会重新呈现函数。如果您在单独的函数中执行此操作,则不会重新渲染它。
- 这个答案现在是否可以防止重新渲染,因为它被package在一个函数中?如果是这样,与上述答案相比,这更好吗? (stackoverflow.com/a/42438769/4602214)
您应该从第一个 .map 返回值,在您的情况下,它是内部 .map
的结果
1
2 3 4 5 |
var elements = myPackage.map(function(myObj){
return myObj.sectionInfo.map(function(myObj1) { // … }); }); |
更新:
根据您的新更新,您可以像这样更改您的代码
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
var App = React.createClass({
section: function(myObj, parentIndex) { switch(myObj1.elementType) { render: function() { return |
React 推荐的方式:React Docs
1
2 3 4 5 6 7 8 9 10 |
const components = {
photo: PhotoStory, video: VideoStory }; function Story(props) { |
正如 Alexander T 的回答中所述,您缺少返回值,但我也建议为您的每个元素添加一个键。 React 的差异算法取决于此值,您可以执行以下操作:
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
render: function(){
var elements = myPackage.map(function(myObj, pIndex){ return myObj.sectionInfo.map(function(myObj1, sIndex){ var key = pIndex + ‘.’ + sIndex; switch(myObj1.elementType) { case 1: return( <Component1 key={key} text={myObj1.text}/> ); case 2: return( <Component2 key={key} text={myObj1.text}/> ) } }) }); return( {elements} ) } |
阅读此处了解更多信息:https://facebook.github.io/react/docs/multiple-components.html#dynamic-children
来源:https://www.codenong.com/37782776/