以指定顺序呈现React组件

时间:2018-01-10 20:21:12

标签: javascript reactjs

有点难以找到关于这种特定模式的任何内容,而且我甚至不确定如何用搜索术语来描述它,所以如果这是一个重复的问题而道歉(尽管我不是认为是)。

我想根据传递给应用程序的订单输出React布局,用户可以通过设置面板进行设置。我的想法是在页面上输出一些不同的容器,我希望用户能够重新安排。请注意,在应用呈现后,此订单不会更改,这一点非常重要。 (我希望用户能够说出"按顺序显示PanelA,PanelC和PanelB")

现在,我已经弄清楚如何使用以下模式来实现这一目标:



// user-ordered array is passed to the app:
    const settings = {
        layout: [
            "panela",
            "panelb",
            "panelc"
        ]
    }

    class MyComponent extends React.Component {
        constructor(props) {
            super(props)
            this.state = {
                // some state
            }
        }
        renderComponentsInOrder() {
            return settings.layout.map(component => {
                switch(component) {
                    case "panela":
                        return 
                            <PanelA {.../* some state */} />
                    case "panelb":
                        return 
                            <PanelB {.../* some state */} />
                    case "panelc":
                        return 
                            <PanelC {.../* some state */} />
                    default: return null
                }
            })
        }

        render() {
            return this.renderComponentsInOrder()
        }
    }
&#13;
&#13;
&#13;

但这让我感到非常低效。每次渲染运行时都不需要重新计算组件的顺序,因为在应用程序运行时顺序不会发生变化。我已经尝试过像memoizing renderComponentsInOrder方法来缓存计算出的布局或重命名settings.layout数组中的值并直接调用它们,但是由于组件需要,我们无法使用任何东西。根据州进行更新。

非常感谢任何帮助或建议。谢谢!

编辑:理想情况下,我正在寻找基于JS的解决方案,因为兼容性是一个问题,我不想完全依赖浏览器的CSS实现。

2 个答案:

答案 0 :(得分:5)

对布兰登给出的答案略有不同。你可以有一个函数来根据state / props生成组件:

const settings = {
    layout: [
        "panela",
        "panelb",
        "panelc"
    ]
};

const panels = settings.layout.map(c => {
  switch (c) {
    case "panela": return (props, state) => <PanelA key="a" foo={state.foo} />
    case "panelb": return (props, state) => <PanelB key="b" bar={state.bar} />
  }
});

// Now use panels array to render:

class MyComponent extends React.Component {
  render() {
    const props = this.props;
    const state = this.state;
    const ordered = panels.map(p => p(props, state));

    return <div>{ordered}</div>
  }
}

答案 1 :(得分:2)

方法1:

在呈现之前,只需将settings数组转换为一个Components数组:

const settings = {
        layout: [
            "panela",
            "panelb",
            "panelc"
        ]
    };

const panels = settings.layout.map(c => {
  switch (c) {
    case "panela": return { Component: PanelA, key: c };
    case "panelb": return { Component: PanelA, key: c };
    ...
  }
});

// Now use panels array to render:

class MyComponent extends React.Component {
  // ...
  renderComponentsInOrder() {
    return panels.map(({Component, key}) => (
      <Component key={key} {.../* some state*/} />
    ));
  }

  // ...
}

方法2:

只需创建一个映射表:

const settings = {
        layout: [
            "panela",
            "panelb",
            "panelc"
        ]
    };

const panelLookup = {
  "panela": PanelA,
  "panelb": PanelB,
   ...
};

// Now use lookup to render:
// Now use panels array to render:

class MyComponent extends React.Component {
  // ...
  renderComponentsInOrder() {
    return settings.layout.map(key => {
      const Component = panelLookup[key];
      return <Component key={key} {.../* some state*/} />;
    });
  }

  // ...
}