【问题标题】:Passing the same props while rendering different elements conditionally in React.js在 React.js 中有条件地渲染不同元素时传递相同的道具
【发布时间】:2018-03-25 19:45:09
【问题描述】:

我有一个名为 Chart 的 React 组件。我想根据从父级传递的道具在其中呈现不同的图表,但具有完全相同的配置。最好的方法是什么?

class Chart extends Component {

  static propTypes = {
    type: PropTypes.string.isRequired
  }

  state = {
    chartData: {
      // some data here 
    }
  }

  render(){
    return(
      this.props.type === 'line' ?
      { <Line
        data={this.state.chartData}
        options={{
          title: {
            display: true,
            text: 'Cities I\'ve lived in',
            fontSize: 25
          },
          legend: {
            display: true,
            position: 'right',
            labels: {
              fontColor: '#000'
            }
          }
        }}
      /> } : this.props.type === 'bar' ?
      { <Bar
          //same stuff here as <Line />
        />
      } : this.props.type === 'pie' ?
      { <Pie
          //same stuff here as <Line />
        /> }
      }
    );
  }
}

不要认为这很重要,因为这个问题很笼统,但我正在使用 react-chartjs-2 / chart.js 2 库来呈现图表。

注意:我尝试使用变量名代替 Line/Bar/Pie,但如果我使用 JSX 或呈现非 html 标记,它就不起作用。也欢迎在使用 JSX 和非 html 标记的同时解决它的更好方法。

【问题讨论】:

    标签: javascript reactjs chart.js


    【解决方案1】:

    两件事:

    • 使用无状态组件,在您的示例中,您没有使用状态。
    • 使用switch 而不是if 语句。

    您的新组件...chart 是解构后的道具。在MDN 上阅读有关解构的更多信息。

    // Chart.js - new component
    
    export const Chart = ({ type, ...chart }) => { 
      switch(type) {
        case 'line':
          return <Line {...chart} />
        case 'bar':
          return <Bar {...chart} />
        case 'pie':
          return <Pie {...chart} />
        default:
         return null;
      }
    }
    

    示例用法

    // App.js 
    
    render() {
      return (
        <div>
          <Chart type="line" options={optionsObject} whateverProp="whatever" />
          <Chart type="bar" options={optionsObject} whateverProp="whatever" />
          <Chart type="pie" options={optionsObject} whateverProp="whatever" />
        </div>
      )
    }
    

    【讨论】:

      【解决方案2】:
      import React, { Component } from 'react';
      
      class Chart extends Component {
        components = {
          Line: Line,
          Bar: Bar,
          Pie: Pie
        };
        render() {
          const TagName = this.components[this.props.tag || 'Line'];
          return
            <TagName
              data={this.state.chartData}
              options={{
              title: {
                display: true,
                text: 'Cities I\'ve lived in',
                fontSize: 25
              },
              legend: {
                display: true,
                position: 'right',
                labels: {
                  fontColor: '#000'
                }
              }
            }}
          />
        }
      }
      export default Chart;
      
      // Call MyComponent using prop tag with required prop Line or Bar or Pie
      <Chart tag='Line' />
      

      注意:- 您也可以将其创建为无状态功能组件。

      【讨论】:

        【解决方案3】:

        我更喜欢将每个图表作为一个组件,这样你可以在该组件中进行图表的具体配置,你的代码会更接近 React 代码的模块化目标,所以以折线图为例:

        class LineChart extends Component {
        
        const chartLegend = {
                    display: true,
                    position: 'right',
                    labels: {
                      fontColor: '#000'
                    }};
        
        const chartTitle = {
                    display: true,
                    text: 'Cities I\'ve lived in',
                    fontSize: 25
                  };
        const chartOptions = {
                  title: chartTitle ,
                  legend: chartLegend           
                }
        
          render(){
            return(
              <Line
                data={this.props.chartData}
                options={chartOptions }
              /> 
            );
          }
        }
        

        现在对于作为容器组件的聊天组件,您可以使用 switch case 或保护条件,正如@loelsonk 所说,我更喜欢除了开关之外还有保护条件:

        class Chart extends Component {
        
          static propTypes = {
            type: PropTypes.string.isRequired
          }
        
          state = {
            chartData: {
              // some data here 
            }
          }
        
          render(){
            if (this.props.type === 'line')
              return <LineChart chartData={...}/>; 
            if (this.props.type === 'bar')
              return <BarChart chartData={...}/>;
            if (this.props.type === 'pie')
              return <PieChart chartData={...}/>;      
          }
        }
        

        通过这种方式,您可以随时轻松替换任何图表实现。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2021-08-04
          • 2022-01-22
          • 2018-03-14
          • 2023-03-03
          • 1970-01-01
          • 2021-02-18
          • 1970-01-01
          • 2022-01-06
          相关资源
          最近更新 更多