0

目前,在我的 react 应用程序中,我有一个父组件,其中包含两个子组件(TrendsComonent 和 BaselineComponent),它们成功加载。父组件还加载了一个下拉组件。

我想要做的是设置一个默认组件最初加载到父组件中,但我想将每个子组件映射到下拉选项。

例如,当访问父组件时,我希望将 TrendsComponent 初始加载为默认值,但将其绑定到趋势下拉选项,并将 BaselineComponent 映射到下拉列表的基线选项。

基本上,我只想根据下拉选项加载组件,而不是一次全部加载

趋势组件.js

import React, { Component } from "react";
import Chart from "react-apexcharts";
import { StyleSheet, css } from 'aphrodite/no-important';

const styles = StyleSheet.create({
    TrendsComponent: {
      display: 'flex',
      flexDirection: 'row',
      justifyContent: 'center',
      textAlign: 'center'
    },
    TrendsTitle: {
      display: 'flex',
      flexDirection: 'row',
      justifyContent: 'center',
      alignItems:'center'
    }
});

class TrendsComponent extends Component {

  render() {
    return (
      <div>
      <div className={css(styles.TrendsTitle)}>
        Net Calories 
      </div>
      <div className={css(styles.TrendsComponent)}>
        <div className={css(styles.TrendsComponent)}>
          <div className="mixed-chart">

            <Chart
            />
          </div>
        </div>
      </div>
      </div>
    );
  }
}

export default TrendsComponent;

基线组件.js

import React, { Component } from "react";
import Chart from "react-apexcharts";
import { StyleSheet, css } from 'aphrodite/no-important';

const styles = StyleSheet.create({
    TrendsComponent: {
      display: 'flex',
      flexDirection: 'row',
      justifyContent: 'center',
      textAlign: 'center'
    },
    TrendsTitle: {
      display: 'flex',
      flexDirection: 'row',
      justifyContent: 'center',
      alignItems:'center'
    }
});

class BaselineComponent extends Component {

  render() {
    return (
      <div>
      <div className={css(styles.TrendsTitle)}>
        Net Calories 
      </div>
      <div >
        <div >
          <div className="mixed-chart">

            <Chart
            />
          </div>
        </div>
      </div>
      </div>
    );
  }
}

export default BaselineComponent;

然后我有当前包含该组件的父组件以及下拉列表

趋势父.js

import React, { Component } from "react";
import Chart from "react-apexcharts";
import { StyleSheet, css } from 'aphrodite/no-important';
import TrendsComponent from './Trendscomponent';
import BaselineComponent from './BaselineComponent';
import TrendDropdownComponent from './TrendDropdownComponent';

class trendparent extends Component {

  render() {
    return (
      <div>
      <div className={css(styles.TrendsTitle)}>
        Net Calories 
      </div>
      <div>
        <div>
          <div>
            <TrendsComponent />
            <BaselineComponent />
          </div>
        </div>
      </div>

      <div style={{height:50}}>
      </div>

      <div>
      <TrendDropdownComponent />
      </div>
      </div>
    );
  }
}

export default trendparent;

下拉.js

import React, { Component } from "react";
import { makeStyles } from '@material-ui/core/styles';
import InputLabel from '@material-ui/core/InputLabel';
import MenuItem from '@material-ui/core/MenuItem';
import FormHelperText from '@material-ui/core/FormHelperText';
import FormControl from '@material-ui/core/FormControl';
import Select from '@material-ui/core/Select';

const useStyles = makeStyles(theme => ({
  formControl: {
    margin: theme.spacing(1),
    minWidth: 220,
  },
  selectEmpty: {
    marginTop: theme.spacing(2),
  },
}));

export default function SimpleSelect() {
  const classes = useStyles();
  const [age, setAge] = React.useState('');

  const inputLabel = React.useRef(null);


  const handleChange = event => {
    setAge(event.target.value);
  };

  return (
    <div>
      <FormControl className={classes.formControl}>
        <InputLabel id="demo-simple-select-label">Calories</InputLabel>
        <Select
          labelId="demo-simple-select-label"
          id="demo-simple-select"
          value={age}
          onChange={handleChange}
        >
          <MenuItem value={10}>Trend</MenuItem>
          <MenuItem value={20}>Baseline</MenuItem>

        </Select>
      </FormControl>
    </div>
  );
}
4

1 回答 1

1

这里的问题是“负载”的真正含义。

1)如果您所说的“加载”实际上意味着只渲染静态导入的组件(已经在文件开头声明),那么您所要做的就是在状态上设置一些默认值,即:

state = {
   renderComponentX: false
}

然后在下拉更改方法上将状态更改为 true:

setState({"renderComponentX":true})

并且内部渲染有一个条件:

{this.state.renderComponentX && <ComponentX />}

2)另一方面,如果你真正想要的是动态加载组件,那么它有点复杂:

您需要创建一个异步加载其他组件的组件。我通常在构造函数中根据组件的状态创建一个随机键数组:

constructor(props) {
    super(props);

    // Dynamic Key Generation for dynamic view loading
    let randomKeys = [];
    while(randomKeys.length < 10){
        let y = Math.random()*10000;
        if(randomKeys.indexOf(y) === -1) randomKeys.push(y);
    }
    this.state = {
        randomKeys
    };
}

这样每个新导入的组件都会有不同的 Key。在这种情况下,它被硬编码为 0,但如果你想在迭代器中创建它,你必须创建一个变量来充当计数器来不断更新索引,例如randomKeys[i]需要i从 0 增长到你想要的组件长度的位置导入。您还需要确保在构造函数中生成足够的键;这个只生成 10 个,因为这是用于手动导入,而不是在迭代器中。

<AsyncComponent key={this.state.randomKeys[0]} getComponent={() => import('../Login/Login.js')} />

我的 AsyncComponent 看起来像这样:

import React from 'react';
import PropTypes from 'prop-types';

export default class AsyncComponent extends React.Component {

    state = {
        AsyncModule: null,

    };

    componentDidMount() {
        let that = this;
        this.unmounted = false;

        this.props.getComponent()
        .then(module => {
            console.log("AsyncComponent loaded module:",module);
            return module.default;
        })
        .then(AsyncModule => {
            if(that.unmounted!==true) {
                that.setState({AsyncModule})
            }   
        });
    }

    componentDidUpdate() {

    }

    componentWillUnmount() {
        this.unmounted = true;
    }

    render() {
        const {loader, ...childProps} = this.props;
        const {AsyncModule} = this.state;

        if(AsyncModule) {
            return (<AsyncModule {...childProps} />)
        }

        if(loader) {
            console.log('loader = ',loader);
            return <div>Loading...</div>;
        }

        return null;
    }
}

AsyncComponent.propTypes = {
    getComponent: PropTypes.func,
    loader: PropTypes.element
};
于 2020-03-19T08:10:00.553 回答